Merge "Assert the updated list of supported ECDHE-PSK cipher suites."
diff --git a/Android.mk b/Android.mk
index 0a9a0b8..fd9bcd1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -50,28 +50,4 @@
 $(info ********************************************************************************)
 endif
 
-
-#
-# "m dalvik-host" for quick minimal host build
-#
-
-ifeq ($(WITH_HOST_DALVIK),true)
-    .PHONY: dalvik-host
-    dalvik-host: \
-        dalvik \
-        $(HOST_OUT)/bin/dalvikvm \
-        $(HOST_OUT)/bin/dexopt \
-        $(HOST_OUT)/lib/libjavacore.so \
-        $(HOST_OUT)/lib/libjavacrypto.so \
-        $(HOST_OUT)/lib/libjavacoretests.so \
-        cacerts-host \
-        core-hostdex \
-        conscrypt-hostdex \
-        okhttp-hostdex \
-        bouncycastle-hostdex \
-        apache-xml-hostdex \
-        apache-harmony-tests-hostdex \
-        $(call intermediates-dir-for,JAVA_LIBRARIES,core-tests,,COMMON)/classes.jar
-endif
-
 include $(subdir_makefiles)
diff --git a/CaCerts.mk b/CaCerts.mk
index 980d0fb..f85f524 100644
--- a/CaCerts.mk
+++ b/CaCerts.mk
@@ -50,10 +50,9 @@
 # This is so that build/target/product/core.mk can use cacerts in PRODUCT_PACKAGES
 ALL_MODULES.cacerts.INSTALLED := $(cacerts_target)
 
-ifeq ($(WITH_HOST_DALVIK),true)
 cacerts_host_directory := $(HOST_OUT)/etc/security/cacerts
 $(foreach cacert, $(cacerts), $(eval $(call include-prebuilt-with-destination-directory,host-cacert-$(notdir $(cacert)),$(cacert),$(cacerts_host_directory))))
-endif
+
 cacerts_host := $(addprefix $(cacerts_host_directory)/,$(foreach cacert,$(cacerts),$(notdir $(cacert))))
 .PHONY: cacerts-host
 cacerts-host: $(cacerts_host)
diff --git a/Docs.mk b/Docs.mk
index 612b3d9..a163d1f 100644
--- a/Docs.mk
+++ b/Docs.mk
@@ -17,8 +17,8 @@
    dalvik/src/main/java/dalvik/annotation \
    dalvik/src/main/java/dalvik/bytecode \
    json/src/main/java \
-   libdvm/src/main/java/dalvik \
-   libdvm/src/main/java/java \
+   libart/src/main/java/dalvik \
+   libart/src/main/java/java \
    luni/src/main/java/android \
    luni/src/main/java/java \
    luni/src/main/java/javax \
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index d97f453..c857390 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -62,7 +62,6 @@
 endif
 endif
 
-libdvm_core_src_files += $(common_core_src_files) $(call all-main-java-files-under,libdvm)
 libart_core_src_files += $(common_core_src_files) $(call all-main-java-files-under,libart)
 
 local_javac_flags=-encoding UTF-8
@@ -76,18 +75,6 @@
 # Definitions to make the core library.
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(libdvm_core_src_files)
-LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVACFLAGS := $(local_javac_flags)
-LOCAL_DX_FLAGS := --core-library
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := core
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
-LOCAL_REQUIRED_MODULES := tzdata
-include $(BUILD_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(libart_core_src_files)
 LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
@@ -108,7 +95,7 @@
 LOCAL_SRC_FILES := $(test_src_files)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit okhttp
+LOCAL_JAVA_LIBRARIES := core-libart okhttp core-junit bouncycastle
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support sqlite-jdbc mockwebserver nist-pkix-tests
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_MODULE := core-tests
@@ -122,7 +109,7 @@
 LOCAL_SRC_FILES := $(call all-test-java-files-under,support)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit
+LOCAL_JAVA_LIBRARIES := core-libart core-junit bouncycastle
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_MODULE := core-tests-support
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
@@ -135,7 +122,7 @@
 LOCAL_SRC_FILES :=  $(call all-test-java-files-under, jsr166-tests)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core core-junit
+LOCAL_JAVA_LIBRARIES := core-libart core-junit
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_MODULE := jsr166-tests
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
@@ -167,62 +154,49 @@
 LOCAL_MODULE := dex-host
 include $(BUILD_HOST_JAVA_LIBRARY)
 
-ifeq ($(WITH_HOST_DALVIK),true)
+# Definitions to make the core library.
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(libart_core_src_files)
+LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_DX_FLAGS := --core-library
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := core-libart-hostdex
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+LOCAL_REQUIRED_MODULES := tzdata-host
+# Should not be dex-preopted as it isn't really a Dalvik boot jar or a
+# regular java library, but part of the image for ART.
+LOCAL_DEX_PREOPT := false
+include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
 
-    # Definitions to make the core library.
-    include $(CLEAR_VARS)
-    LOCAL_SRC_FILES := $(libdvm_core_src_files)
-    LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
-    LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_JAVACFLAGS := $(local_javac_flags)
-    LOCAL_DX_FLAGS := --core-library
-    LOCAL_MODULE_TAGS := optional
-    LOCAL_MODULE := core-hostdex
-    LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
-    LOCAL_REQUIRED_MODULES := tzdata-host
-    include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
-
-    include $(CLEAR_VARS)
-    LOCAL_SRC_FILES := $(libart_core_src_files)
-    LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
-    LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_JAVACFLAGS := $(local_javac_flags)
-    LOCAL_DX_FLAGS := --core-library
-    LOCAL_MODULE_TAGS := optional
-    LOCAL_MODULE := core-libart-hostdex
-    LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
-    LOCAL_REQUIRED_MODULES := tzdata-host
-    # Should not be dex-preopted as it isn't really a Dalvik boot jar or a
-    # regular java library, but part of the image for ART.
-    LOCAL_DEX_PREOPT := false
-    include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
-
-    # Make the core-tests library.
-    ifeq ($(LIBCORE_SKIP_TESTS),)
+# Make the core-tests library.
+ifeq ($(LIBCORE_SKIP_TESTS),)
     include $(CLEAR_VARS)
     LOCAL_SRC_FILES := $(test_src_files)
     LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
-    LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-junit-hostdex core-tests-support-hostdex okhttp-hostdex
+    LOCAL_NO_STANDARD_LIBRARIES := true
+    LOCAL_JAVA_LIBRARIES := core-libart-hostdex okhttp-hostdex bouncycastle-hostdex core-junit-hostdex core-tests-support-hostdex
     LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
     LOCAL_MODULE := core-tests-hostdex
     LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
     include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
-    endif
+endif
 
-    # Make the core-tests-support library.
-    ifeq ($(LIBCORE_SKIP_TESTS),)
+# Make the core-tests-support library.
+ifeq ($(LIBCORE_SKIP_TESTS),)
     include $(CLEAR_VARS)
     LOCAL_SRC_FILES := $(call all-test-java-files-under,support)
     LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
-    LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-junit-hostdex
+    LOCAL_NO_STANDARD_LIBRARIES := true
+    LOCAL_JAVA_LIBRARIES := core-libart-hostdex core-junit-hostdex bouncycastle-hostdex
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
     LOCAL_MODULE := core-tests-support-hostdex
     LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
     include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
-    endif
 endif
 
 #
diff --git a/NativeCode.mk b/NativeCode.mk
index 2a16598..98e87b0 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -112,22 +112,24 @@
 # Build for the host.
 #
 
-ifeq ($(WITH_HOST_DALVIK),true)
-    include $(CLEAR_VARS)
-    LOCAL_CLANG := true
-    LOCAL_SRC_FILES += $(core_src_files)
-    LOCAL_CFLAGS += $(core_cflags)
-    LOCAL_C_INCLUDES += $(core_c_includes)
-    LOCAL_CPPFLAGS += $(core_cppflags)
-    LOCAL_LDLIBS += -ldl -lpthread -lrt
-    LOCAL_MODULE_TAGS := optional
-    LOCAL_MODULE := libjavacore
-    LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
-    LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat-host libicuuc-host libicui18n-host libcrypto-host libz-host
-    LOCAL_STATIC_LIBRARIES += $(core_static_libraries) libziparchive-host libutils
-    include $(BUILD_HOST_SHARED_LIBRARY)
+include $(CLEAR_VARS)
+LOCAL_CLANG := true
+LOCAL_SRC_FILES += $(core_src_files)
+LOCAL_CFLAGS += $(core_cflags)
+LOCAL_C_INCLUDES += $(core_c_includes)
+LOCAL_CPPFLAGS += $(core_cppflags)
+LOCAL_LDLIBS += -ldl -lpthread
+ifeq ($(HOST_OS),linux)
+LOCAL_LDLIBS += -lrt
+endif
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libjavacore
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
+LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat-host libicuuc-host libicui18n-host libcrypto-host libz-host
+LOCAL_STATIC_LIBRARIES += $(core_static_libraries) libziparchive-host libutils
+include $(BUILD_HOST_SHARED_LIBRARY)
 
-    ifeq ($(LIBCORE_SKIP_TESTS),)
+ifeq ($(LIBCORE_SKIP_TESTS),)
     include $(CLEAR_VARS)
     LOCAL_CLANG := true
     LOCAL_SRC_FILES += $(core_test_files)
@@ -140,5 +142,4 @@
     LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
     LOCAL_SHARED_LIBRARIES := libcrypto-host
     include $(BUILD_HOST_SHARED_LIBRARY)
-    endif # LIBCORE_SKIP_TESTS
-endif
+endif # LIBCORE_SKIP_TESTS
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index b91894f..c0a38a0 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -1,34 +1,39 @@
+# -*- mode: makefile -*-
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 LOCAL_PATH:= $(call my-dir)
-##################################################
-include $(CLEAR_VARS)
 
 ifeq ($(LIBCORE_SKIP_TESTS),)
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
+##################################################
+include $(CLEAR_VARS)
 LOCAL_MODULE := benchmarks
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-	caliper-prebuilt \
-	core-tests
-
-LOCAL_JAVA_LIBRARIES := \
-	bouncycastle \
-	conscrypt \
-	core
-
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := caliper-prebuilt core-tests
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-libart conscrypt core-junit bouncycastle framework
 LOCAL_MODULE_TAGS := tests
-
 LOCAL_MODULE_PATH := $(PRODUCT_OUT)/data/caliperperf
-
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_JAVA_LIBRARY)
 
 ##################################################
 # Prebuilt Java libraries
 include $(CLEAR_VARS)
-
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
-	caliper-prebuilt:libs/caliper.jar
-
+LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := caliper-prebuilt:libs/caliper.jar
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_MULTI_PREBUILT)
+
 endif
diff --git a/benchmarks/src/benchmarks/regression/IcuBenchmark.java b/benchmarks/src/benchmarks/regression/IcuBenchmark.java
index ee8270a..2aed36b 100644
--- a/benchmarks/src/benchmarks/regression/IcuBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/IcuBenchmark.java
@@ -26,7 +26,7 @@
 public class IcuBenchmark extends SimpleBenchmark {
   public void time_getBestDateTimePattern(int reps) throws Exception {
     for (int rep = 0; rep < reps; ++rep) {
-      ICU.getBestDateTimePattern("dEEEMMM", "US");
+      ICU.getBestDateTimePattern("dEEEMMM", new Locale("en", "US"));
     }
   }
 }
diff --git a/benchmarks/src/benchmarks/regression/StringCaseMappingBenchmark.java b/benchmarks/src/benchmarks/regression/StringCaseMappingBenchmark.java
index cde257b..ae6b6b6 100644
--- a/benchmarks/src/benchmarks/regression/StringCaseMappingBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/StringCaseMappingBenchmark.java
@@ -106,13 +106,13 @@
 
     public void timeToUpperCase_ICU(int reps) {
         for (int i = 0; i < reps; ++i) {
-            libcore.icu.ICU.toUpperCase(s.value, Locale.US.toString());
+            libcore.icu.ICU.toUpperCase(s.value, Locale.US);
         }
     }
 
     public void timeToLowerCase_ICU(int reps) {
         for (int i = 0; i < reps; ++i) {
-            libcore.icu.ICU.toLowerCase(s.value, Locale.US.toString());
+            libcore.icu.ICU.toLowerCase(s.value, Locale.US);
         }
     }
 
diff --git a/expectations/icebox.txt b/expectations/icebox.txt
index 07449c6..8764185 100644
--- a/expectations/icebox.txt
+++ b/expectations/icebox.txt
@@ -3,16 +3,6 @@
  */
 [
 {
- description: "javasqlite doesn't honor query timeouts",
- bug: 5213614,
- names: [
-   "libcore.sqlite.QueryTimeoutTest#testExecuteUpdate",
-   "libcore.sqlite.QueryTimeoutTest#testPreparedStatementFetch",
-   "libcore.sqlite.QueryTimeoutTest#testPreparedStatementUpdate",
-   "libcore.sqlite.QueryTimeoutTest#testTimeoutAndStatementReuse"
-  ]
-},
-{
   description: "Dalvik doesn't support XML Schemas, DTDs or validation",
   bug: 3268630,
   name: "libcore.xml.DomTest#testEntityDeclarations",
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 108fa6e..698ebc5 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -755,70 +755,6 @@
   name: "tests.api.javax.net.ssl.TrustManagerFactory1Test#test_initLjavax_net_ssl_ManagerFactoryParameters"
 },
 {
-  description: "method test fails once in a while. Cannot be sure that exception is thrown in every test execution.",
-  bug: 3403706,
-  name: "libcore.sqlite.OldDatabaseTest#testBusy_handler"
-},
-{
-  description: "Database does not lock values",
-  bug: 3403706,
-  name: "libcore.sqlite.OldDatabaseTest#testBusy_timeout"
-},
-{
-  description: "Returns wrong number for updates: returns value > 1 for select.",
-  bug: 3403706,
-  name: "libcore.sqlite.OldDatabaseTest#testChanges"
-},
-{
-  description: "Aggregation function not called",
-  bug: 3403706,
-  name: "libcore.sqlite.OldDatabaseTest#testCreate_aggregate"
-},
-{
-  description: "Reason for failure unknown: Database should be locked. Specification of interrupt is scarce.",
-  result: EXEC_FAILED,
-  name: "libcore.sqlite.OldDatabaseTest#testInterrupt"
-},
-{
-  description: "not supported",
-  bug: 3403706,
-  name: "libcore.sqlite.OldDatabaseTest#testOpen_blob"
-},
-{
-  description: "Callback never made for authorization. Results of private table are returned without further checks.",
-  bug: 3403706,
-  name: "libcore.sqlite.OldDatabaseTest#testSet_authorizer"
-},
-{
-  description: "ASCII encoding does not work: a UTF encoded val is returned. Spec is not sufficient. Might be that test impl is wrong or String constructor for the ASCII encoding.",
-  bug: 3403706,
-  name: "libcore.sqlite.OldDatabaseTest#testSet_encoding"
-},
-{
-  description: "db.open_blob is not supported.",
-  bug: 3403706,
-  name: "libcore.sqlite.OldBlobTest#testBlob"
-},
-{
-  description: "Wrong value is returned in case of a prepared statement to which a '*' bound",
-  bug: 3403706,
-  name: "libcore.sqlite.OldStmtTest#testColumn_count"
-},
-{
-  description: "ZeroBlob not supported",
-  bug: 3403706,
-  name: "libcore.sqlite.OldFunctionContextTest#testSet_result_zeroblob"
-},
-{
-  description: "SQLite test fail",
-  bug: 3403706,
-  names: [
-    "libcore.sqlite.OldDatabaseTest#testGet_tableString",
-    "libcore.sqlite.OldDatabaseTest#testGet_tableStringStringArrayTableResult",
-    "libcore.sqlite.OldStmtTest#testColumn_type"
-  ]
-},
-{
   modes: [ "jvm" ],
   description: "The RI's formatter doesn't localize arabic properly",
   names: [
@@ -1441,10 +1377,5 @@
   description: "Known failure in GregorianCalendarTest",
   bug: 12778197,
   name: "org.apache.harmony.tests.java.util.GregorianCalendarTest#test_computeTime"
-},
-{
-  description: "Large test that ends in a timeout during CTS runs",
-  bug: 5513723,
-  name: "libcore.java.security.KeyPairGeneratorTest#test_getInstance"
 }
 ]
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/RuntimeTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/RuntimeTest.java
index 08a4fa9..17f822d 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/RuntimeTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/RuntimeTest.java
@@ -19,6 +19,8 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Vector;
 
 public class RuntimeTest extends junit.framework.TestCase {
@@ -82,14 +84,6 @@
     }
 
     /**
-     * java.lang.Runtime#freeMemory()
-     */
-    public void test_freeMemory() {
-        // Test for method long java.lang.Runtime.freeMemory()
-        assertTrue("freeMemory returned nonsense value", r.freeMemory() > 0);
-    }
-
-    /**
      * java.lang.Runtime#gc()
      */
     public void test_gc() {
@@ -142,12 +136,28 @@
     }
 
     /**
-     * java.lang.Runtime#totalMemory()
+     * java.lang.Runtime#freeMemory() / java.lang.Runtime#totalMemory() /
+     * java.lang.Runtime#maxMemory()
      */
-    public void test_totalMemory() {
-        // Test for method long java.lang.Runtime.totalMemory()
-        assertTrue("totalMemory returned nonsense value", r.totalMemory() >= r
-                .freeMemory());
+    public void test_memory() {
+        assertTrue("freeMemory <= 0", r.freeMemory() > 0);
+        assertTrue("totalMemory() < freeMemory()", r.totalMemory() >= r.freeMemory());
+        assertTrue("maxMemory() < totalMemory()", r.maxMemory() >= r.totalMemory());
+    }
+
+    public void test_freeMemory() {
+        // Heap might grow or do GC at any time, so we can't really test a lot. Hence we are just
+        // doing some basic sanity checks here.
+        long freeBefore = r.freeMemory();
+        List<byte[]> arrays = new ArrayList<byte[]>();
+        for (int i = 1; i < 10; i++) {
+            arrays.add(new byte[10000]);
+        }
+        long freeAfter =  r.freeMemory();
+
+        // If totalMemory() has grown/shrunk freeMemory() might have gone down or up, but the
+        // freeMemory is unlikely to stay the same.
+        assertTrue("free memory must change with allocations", freeAfter != freeBefore);
     }
 
     public RuntimeTest() {
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
index 6a75746..e3e1207 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
@@ -18,7 +18,6 @@
 package org.apache.harmony.tests.java.net;
 
 import java.io.IOException;
-import java.io.InterruptedIOException;
 import java.net.BindException;
 import java.net.DatagramPacket;
 import java.net.Inet4Address;
@@ -29,8 +28,10 @@
 import java.net.NetworkInterface;
 import java.net.SocketAddress;
 import java.net.SocketException;
+import java.net.SocketTimeoutException;
 import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.List;
 
 public class MulticastSocketTest extends junit.framework.TestCase {
 
@@ -52,158 +53,124 @@
     private static InetAddress GOOD_IPv6 = lookup("ff05::7:7");
     private static InetAddress BAD_IPv6 = lookup("ff05::7:8");
 
-    static class MulticastServer extends Thread {
+    private NetworkInterface loopbackInterface;
+    private NetworkInterface ipv4NetworkInterface;
+    private NetworkInterface ipv6NetworkInterface;
 
-        public final MulticastSocket ms;
-        public final byte[] rbuf = new byte[512];
-        public final DatagramPacket rdp;
-        private final InetAddress groupAddr;
-        private final NetworkInterface groupNI;
+    @Override
+    protected void setUp() throws Exception {
+        // The loopback interface isn't actually useful for sending/receiving multicast messages
+        // but it can be used as a dummy for tests where that does not matter.
+        loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
+        assertNotNull(loopbackInterface);
+        assertTrue(loopbackInterface.isLoopback());
+        assertFalse(loopbackInterface.supportsMulticast());
 
-        private volatile boolean running = true;
+        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+        assertNotNull(interfaces);
 
-        public MulticastServer(InetAddress anAddress, int aPort) throws java.io.IOException {
-            rbuf[0] = -1;
-            rdp = new DatagramPacket(rbuf, rbuf.length);
-            ms = new MulticastSocket(aPort);
-            ms.setSoTimeout(2000);
-
-            groupAddr = anAddress;
-            groupNI = null;
-
-            ms.joinGroup(groupAddr);
-        }
-
-        public MulticastServer(InetAddress anAddress, int aPort,
-                NetworkInterface netInterface) throws java.io.IOException {
-            rbuf[0] = -1;
-            rdp = new DatagramPacket(rbuf, rbuf.length);
-            ms = new MulticastSocket(aPort);
-            ms.setSoTimeout(2000);
-
-            groupAddr = anAddress;
-            groupNI = netInterface;
-
-            ms.joinGroup(new InetSocketAddress(groupAddr, ms.getLocalPort()), groupNI);
-        }
-
-        public void run() {
-            try {
-                byte[] tmpbuf = new byte[512];
-                DatagramPacket tmpPack = new DatagramPacket(tmpbuf, tmpbuf.length);
-
-                while (running) {
-                    try {
-                        ms.receive(tmpPack);
-                        System.arraycopy(tmpPack.getData(), 0, rdp.getData(), rdp.getOffset(),
-                                tmpPack.getLength());
-                        rdp.setLength(tmpPack.getLength());
-                        rdp.setAddress(tmpPack.getAddress());
-                        rdp.setPort(tmpPack.getPort());
-                    } catch (InterruptedIOException e) {
+        while (interfaces.hasMoreElements()
+                && (ipv4NetworkInterface == null || ipv6NetworkInterface == null)) {
+            NetworkInterface nextInterface = interfaces.nextElement();
+            if (willWorkForMulticast(nextInterface)) {
+                Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
+                while (addresses.hasMoreElements()) {
+                    final InetAddress nextAddress = addresses.nextElement();
+                    if (nextAddress instanceof Inet6Address && ipv6NetworkInterface == null) {
+                        ipv6NetworkInterface = nextInterface;
+                    } else if (nextAddress instanceof Inet4Address && ipv4NetworkInterface == null) {
+                        ipv4NetworkInterface = nextInterface;
                     }
                 }
-            } catch (java.io.IOException e) {
-                fail();
-            } finally {
-                ms.close();
             }
         }
-
-        public void stopServer() {
-            running = false;
-            try {
-                ms.leaveGroup(groupAddr);
-            } catch (IOException e) {
-            }
-        }
+        assertTrue("Test environment must have at least one interface capable of multicast for IPv4"
+                + " and IPv6",
+                ipv4NetworkInterface != null && ipv6NetworkInterface != null);
     }
 
-    private NetworkInterface loopbackInterface;
-    private NetworkInterface networkInterface1;
-    private NetworkInterface IPV6networkInterface1;
-
     public void test_Constructor() throws IOException {
-        // regression test for 497
+        // Regression test for 497.
         MulticastSocket s = new MulticastSocket();
-        // regression test for Harmony-1162
+        // Regression test for Harmony-1162.
         assertTrue(s.getReuseAddress());
+
+        s.close();
     }
 
     public void test_ConstructorI() throws IOException {
         MulticastSocket orig = new MulticastSocket();
         int port = orig.getLocalPort();
         orig.close();
-        MulticastSocket dup = null;
-        try {
-            dup = new MulticastSocket(port);
-            // regression test for Harmony-1162
-            assertTrue(dup.getReuseAddress());
-        } catch (IOException e) {
-            fail("duplicate binding not allowed: " + e);
-        }
-        if (dup != null) {
-            dup.close();
-        }
+
+        MulticastSocket dup = new MulticastSocket(port);
+        // Regression test for Harmony-1162.
+        assertTrue(dup.getReuseAddress());
+        dup.close();
     }
 
     public void test_getInterface() throws Exception {
-        // validate that we get the expected response when one was not set
+        // Validate that we get the expected response when one was not set.
         MulticastSocket mss = new MulticastSocket(0);
-        // we expect an ANY address in this case
+        // We expect an ANY address in this case.
         assertTrue(mss.getInterface().isAnyLocalAddress());
 
-        // validate that we get the expected response when we set via
-        // setInterface
-        Enumeration addresses = networkInterface1.getInetAddresses();
+        // Validate that we get the expected response when we set via setInterface.
+        Enumeration addresses = ipv4NetworkInterface.getInetAddresses();
         if (addresses.hasMoreElements()) {
             InetAddress firstAddress = (InetAddress) addresses.nextElement();
             mss.setInterface(firstAddress);
-            assertEquals("getNetworkInterface did not return interface set by setInterface", firstAddress, mss.getInterface());
+            assertEquals("getNetworkInterface did not return interface set by setInterface",
+                    firstAddress, mss.getInterface());
 
             mss.close();
             mss = new MulticastSocket(0);
-            mss.setNetworkInterface(networkInterface1);
-            assertEquals("getInterface did not return interface set by setNetworkInterface", networkInterface1, NetworkInterface.getByInetAddress(mss.getInterface()));
+            mss.setNetworkInterface(ipv4NetworkInterface);
+            assertEquals("getInterface did not return interface set by setNetworkInterface",
+                    ipv4NetworkInterface, NetworkInterface.getByInetAddress(mss.getInterface()));
         }
 
         mss.close();
     }
 
     public void test_getNetworkInterface() throws IOException {
-        // validate that we get the expected response when one was not set
+        // Validate that we get the expected response when one was not set.
         MulticastSocket mss = new MulticastSocket(0);
         NetworkInterface theInterface = mss.getNetworkInterface();
-        assertTrue("network interface returned wrong network interface when not set:" + theInterface,
+        assertTrue(
+                "network interface returned wrong network interface when not set:" + theInterface,
                 theInterface.getInetAddresses().hasMoreElements());
-        InetAddress firstAddress = (InetAddress) theInterface.getInetAddresses().nextElement();
-        // validate we the first address in the network interface is the ANY address
+        InetAddress firstAddress = theInterface.getInetAddresses().nextElement();
+        // Validate we the first address in the network interface is the ANY address.
         assertTrue(firstAddress.isAnyLocalAddress());
 
-        mss.setNetworkInterface(networkInterface1);
+        mss.setNetworkInterface(ipv4NetworkInterface);
         assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
-                networkInterface1, mss.getNetworkInterface());
+                ipv4NetworkInterface, mss.getNetworkInterface());
 
         mss.setNetworkInterface(loopbackInterface);
-        assertEquals("getNetworkInterface did not return network interface set by second setNetworkInterface call",
+        assertEquals(
+                "getNetworkInterface did not return network interface set by second"
+                        + " setNetworkInterface call",
                 loopbackInterface, mss.getNetworkInterface());
         mss.close();
 
-        mss = new MulticastSocket(0);
-        if (IPV6networkInterface1 != null) {
-            mss.setNetworkInterface(IPV6networkInterface1);
+        if (ipv6NetworkInterface != null) {
+            mss = new MulticastSocket(0);
+            mss.setNetworkInterface(ipv6NetworkInterface);
             assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
-                    IPV6networkInterface1, mss.getNetworkInterface());
+                    ipv6NetworkInterface, mss.getNetworkInterface());
+            mss.close();
         }
 
-        // validate that we get the expected response when we set via setInterface
+        // Validate that we get the expected response when we set via setInterface.
         mss = new MulticastSocket(0);
-        Enumeration addresses = networkInterface1.getInetAddresses();
+        Enumeration addresses = ipv4NetworkInterface.getInetAddresses();
         if (addresses.hasMoreElements()) {
             firstAddress = (InetAddress) addresses.nextElement();
             mss.setInterface(firstAddress);
             assertEquals("getNetworkInterface did not return interface set by setInterface",
-                    networkInterface1, mss.getNetworkInterface());
+                    ipv4NetworkInterface, mss.getNetworkInterface());
         }
         mss.close();
     }
@@ -214,12 +181,14 @@
         assertEquals("Returned incorrect 1st TTL", 120, mss.getTimeToLive());
         mss.setTimeToLive(220);
         assertEquals("Returned incorrect 2nd TTL", 220, mss.getTimeToLive());
+        mss.close();
     }
 
     public void test_getTTL() throws Exception {
         MulticastSocket mss = new MulticastSocket();
         mss.setTTL((byte) 120);
         assertEquals("Returned incorrect TTL", 120, mss.getTTL());
+        mss.close();
     }
 
     public void test_joinGroupLjava_net_InetAddress_IPv4() throws Exception {
@@ -231,19 +200,23 @@
     }
 
     private void test_joinGroupLjava_net_InetAddress(InetAddress group) throws Exception {
-        MulticastServer server = new MulticastServer(group, 0);
-        server.start();
-        Thread.sleep(1000);
+        MulticastSocket receivingSocket = createReceivingSocket(0);
+        receivingSocket.joinGroup(group);
+
         String msg = "Hello World";
-        MulticastSocket mss = new MulticastSocket(server.ms.getLocalPort());
-        DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg.length(), group,
-                server.ms.getLocalPort());
-        mss.send(sdp, (byte) 10);
-        Thread.sleep(1000);
-        String receivedMessage = new String(server.rdp.getData(), 0, server.rdp.getLength());
+        MulticastSocket sendingSocket = new MulticastSocket(receivingSocket.getLocalPort());
+        InetSocketAddress groupAddress =
+                new InetSocketAddress(group, receivingSocket.getLocalPort());
+        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+        sendingSocket.send(sdp, (byte) 10 /* ttl */);
+
+        DatagramPacket rdp = createReceiveDatagramPacket();
+        receivingSocket.receive(rdp);
+        String receivedMessage = extractMessage(rdp);
         assertEquals("Group member did not recv data", msg, receivedMessage);
-        mss.close();
-        server.stopServer();
+
+        sendingSocket.close();
+        receivingSocket.close();
     }
 
     public void test_joinGroup_null_null() throws Exception {
@@ -276,52 +249,64 @@
         mss.close();
     }
 
-    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4() throws Exception {
-        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(GOOD_IPv4, BAD_IPv4);
+    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
+            throws Exception {
+        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+                ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
     }
 
-    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6() throws Exception {
-        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(GOOD_IPv6, BAD_IPv6);
+    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
+            throws Exception {
+        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+                ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
     }
 
-    private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(InetAddress group, InetAddress group2) throws Exception {
+    private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+            NetworkInterface networkInterface, InetAddress group, InetAddress group2)
+            throws Exception {
         // Check that we can join a group using a null network interface.
-        MulticastSocket mss = new MulticastSocket(0);
-        SocketAddress groupSockAddr = new InetSocketAddress(group, mss.getLocalPort());
+        MulticastSocket sendingSocket = new MulticastSocket(0);
+        SocketAddress groupSockAddr = new InetSocketAddress(group, sendingSocket.getLocalPort());
+        sendingSocket.joinGroup(groupSockAddr, null);
+        sendingSocket.setTimeToLive(2);
 
-        mss.joinGroup(groupSockAddr, null);
-        mss.setTimeToLive(2);
-        Thread.sleep(1000);
+        MulticastSocket receivingSocket = createReceivingSocket(0);
+        InetSocketAddress groupAddress =
+                new InetSocketAddress(group, receivingSocket.getLocalPort());
+        receivingSocket.joinGroup(groupAddress, networkInterface);
 
-        // set up the server and join the group on networkInterface1
-        MulticastServer server = new MulticastServer(group, 0, networkInterface1);
-        server.start();
-        Thread.sleep(1000);
         String msg = "Hello World";
-        DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg.length(), group,
-                server.ms.getLocalPort());
-        mss.setTimeToLive(2);
-        mss.send(sdp);
-        Thread.sleep(1000);
-        // now validate that we received the data as expected
-        assertEquals("Group member did not recv data", msg, new String(server.rdp.getData(), 0, server.rdp.getLength()));
-        server.stopServer();
-        mss.close();
+        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+        sendingSocket.send(sdp);
 
-        server = new MulticastServer(group, 0, networkInterface1);
-        server.start();
-        Thread.sleep(1000);
+        DatagramPacket rdp = createReceiveDatagramPacket();
+        receivingSocket.receive(rdp);
+        // Now validate that we received the data as expected.
+        assertEquals("Group member did not recv data", msg, extractMessage(rdp));
+        receivingSocket.close();
+        sendingSocket.close();
 
-        mss = new MulticastSocket(0);
-        mss.setTimeToLive(10);
+        receivingSocket = createReceivingSocket(0);
+        groupAddress = new InetSocketAddress(group, receivingSocket.getLocalPort());
+        receivingSocket.joinGroup(groupAddress, networkInterface);
+
+        sendingSocket = new MulticastSocket(0);
+        sendingSocket.setTimeToLive(10);
         msg = "Hello World - Different Group";
-        sdp = new DatagramPacket(msg.getBytes(), msg.length(), group2, server.ms.getLocalPort());
-        mss.send(sdp);
-        Thread.sleep(1000);
-        assertFalse("Group member received data when sent on different group: ",
-                new String(server.rdp.getData(), 0, server.rdp.getLength()).equals(msg));
-        server.stopServer();
-        mss.close();
+        InetSocketAddress group2Address =
+                new InetSocketAddress(group2, receivingSocket.getLocalPort());
+        sdp = createSendDatagramPacket(group2Address, msg);
+        sendingSocket.send(sdp);
+
+        rdp = createReceiveDatagramPacket();
+        try {
+            receivingSocket.receive(rdp);
+            fail("Expected timeout");
+        } catch (SocketTimeoutException expected) {
+        }
+
+        receivingSocket.close();
+        sendingSocket.close();
     }
 
     public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws Exception {
@@ -329,27 +314,19 @@
         // received on that interface. This test is only really useful on devices with multiple
         // non-loopback interfaces.
 
-        ArrayList<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
+        List<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
         Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
         while (theInterfaces.hasMoreElements()) {
             NetworkInterface thisInterface = theInterfaces.nextElement();
-            if (thisInterface.getInetAddresses().hasMoreElements()) {
+            // Skip interfaces that do not support multicast - there's no point in proving
+            // they cannot send / receive multicast messages.
+            if (willWorkForMulticast(thisInterface)) {
                 realInterfaces.add(thisInterface);
             }
         }
 
-        for (int i = 0; i < realInterfaces.size(); i++) {
-            NetworkInterface thisInterface = realInterfaces.get(i);
-            if (!thisInterface.supportsMulticast()) {
-                // Skip interfaces that do not support multicast - there's no point in proving
-                // they cannot send / receive multicast messages.
-                continue;
-            }
-
-            // get the first address on the interface
-
-            // start server which is joined to the group and has
-            // only asked for packets on this interface
+        for (NetworkInterface thisInterface : realInterfaces) {
+            // Find a suitable group IP and interface to use to sent packets to thisInterface.
             Enumeration<InetAddress> addresses = thisInterface.getInetAddresses();
 
             NetworkInterface sendingInterface = null;
@@ -358,57 +335,69 @@
                 InetAddress firstAddress = addresses.nextElement();
                 if (firstAddress instanceof Inet4Address) {
                     group = GOOD_IPv4;
-                    sendingInterface = networkInterface1;
+                    sendingInterface = ipv4NetworkInterface;
                 } else {
                     // if this interface only seems to support IPV6 addresses
                     group = GOOD_IPv6;
-                    sendingInterface = IPV6networkInterface1;
+                    sendingInterface = ipv6NetworkInterface;
                 }
             }
 
-            MulticastServer server = new MulticastServer(group, 0, thisInterface);
-            server.start();
-            Thread.sleep(1000);
+            // Create a receivingSocket which is joined to the group and has only asked for packets
+            // on thisInterface.
+            MulticastSocket receivingSocket = createReceivingSocket(0);
+            InetSocketAddress groupAddress =
+                    new InetSocketAddress(group, receivingSocket.getLocalPort());
+            receivingSocket.joinGroup(groupAddress, thisInterface);
 
-            // Now send out a package on interface networkInterface 1. We should
-            // only see the packet if we send it on interface 1
-            MulticastSocket mss = new MulticastSocket(0);
-            mss.setNetworkInterface(sendingInterface);
-            String msg = "Hello World - Again" + thisInterface.getName();
-            DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg.length(), group,
-                    server.ms.getLocalPort());
-            mss.send(sdp);
-            Thread.sleep(1000);
-            if (thisInterface.equals(sendingInterface)) {
+            // Now send out a packet on sendingInterface. We should only see the packet if we send
+            // it on thisInterface.
+            MulticastSocket sendingSocket = new MulticastSocket(0);
+            sendingSocket.setNetworkInterface(sendingInterface);
+            String msg = "Hello World - Again " + thisInterface.getName();
+            DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+            sendingSocket.send(sdp);
+
+            DatagramPacket rdp = createReceiveDatagramPacket();
+            try {
+                receivingSocket.receive(rdp);
+
+                // If the packet is received....
+                assertEquals(thisInterface, sendingInterface);
                 assertEquals("Group member did not recv data when bound on specific interface",
-                        msg, new String(server.rdp.getData(), 0, server.rdp.getLength()));
-            } else {
-                assertFalse("Group member received data on other interface when only asked for it on one interface: ",
-                        new String(server.rdp.getData(), 0, server.rdp.getLength()).equals(msg));
+                        msg, extractMessage(rdp));
+            } catch (SocketTimeoutException e) {
+                // If the packet was not received...
+                assertTrue(!thisInterface.equals(sendingInterface));
             }
 
-            server.stopServer();
-            mss.close();
+            receivingSocket.close();
+            sendingSocket.close();
         }
     }
 
-    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv4() throws Exception {
-        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(GOOD_IPv4);
+    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv4()
+            throws Exception {
+        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
+                ipv4NetworkInterface, GOOD_IPv4);
     }
 
-    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv6() throws Exception {
-        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(GOOD_IPv6);
+    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv6()
+            throws Exception {
+        test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
+                ipv6NetworkInterface, GOOD_IPv6);
     }
 
-    private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(InetAddress group) throws Exception {
-        // validate that we can join the same address on two
-        // different interfaces but not on the same interface
+    private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
+            NetworkInterface networkInterface, InetAddress group) throws Exception {
+        // Validate that we can join the same address on two different interfaces but not on the
+        // same interface.
         MulticastSocket mss = new MulticastSocket(0);
         SocketAddress groupSockAddr = new InetSocketAddress(group, mss.getLocalPort());
-        mss.joinGroup(groupSockAddr, networkInterface1);
+        mss.joinGroup(groupSockAddr, networkInterface);
         mss.joinGroup(groupSockAddr, loopbackInterface);
         try {
-            mss.joinGroup(groupSockAddr, networkInterface1);
+            mss.joinGroup(groupSockAddr, networkInterface);
             fail("Did not get expected exception when joining for second time on same interface");
         } catch (IOException e) {
         }
@@ -426,9 +415,9 @@
     private void test_leaveGroupLjava_net_InetAddress(InetAddress group) throws Exception {
         String msg = "Hello World";
         MulticastSocket mss = new MulticastSocket(0);
-        DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg.length(), group,
-                mss.getLocalPort());
-        mss.send(sdp, (byte) 10);
+        InetSocketAddress groupAddress = new InetSocketAddress(group, mss.getLocalPort());
+        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+        mss.send(sdp, (byte) 10 /* ttl */);
         try {
             // Try to leave a group we didn't join.
             mss.leaveGroup(group);
@@ -468,15 +457,21 @@
         mss.close();
     }
 
-    public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4() throws Exception {
-        test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(GOOD_IPv4, BAD_IPv4);
+    public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
+            throws Exception {
+        test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+                ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
     }
 
-    public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6() throws Exception {
-        test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(GOOD_IPv6, BAD_IPv6);
+    public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
+            throws Exception {
+        test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+                ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
     }
 
-    private void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(InetAddress group, InetAddress group2) throws Exception {
+    private void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+            NetworkInterface networkInterface, InetAddress group, InetAddress group2)
+            throws Exception {
         SocketAddress groupSockAddr = null;
         SocketAddress groupSockAddr2 = null;
 
@@ -491,20 +486,20 @@
         }
 
         groupSockAddr2 = new InetSocketAddress(group2, mss.getLocalPort());
-        mss.joinGroup(groupSockAddr, networkInterface1);
+        mss.joinGroup(groupSockAddr, networkInterface);
         try {
-            mss.leaveGroup(groupSockAddr2, networkInterface1);
+            mss.leaveGroup(groupSockAddr2, networkInterface);
             fail("Did not get exception when trying to leave group that was never joined");
         } catch (IOException expected) {
         }
 
-        mss.leaveGroup(groupSockAddr, networkInterface1);
+        mss.leaveGroup(groupSockAddr, networkInterface);
 
-        mss.joinGroup(groupSockAddr, networkInterface1);
+        mss.joinGroup(groupSockAddr, networkInterface);
         try {
             mss.leaveGroup(groupSockAddr, loopbackInterface);
             fail("Did not get exception when trying to leave group on wrong interface " +
-                    "joined on [" + networkInterface1 + "] left on [" + loopbackInterface + "]");
+                    "joined on [" + networkInterface + "] left on [" + loopbackInterface + "]");
         } catch (IOException expected) {
         }
     }
@@ -519,31 +514,36 @@
 
     private void test_sendLjava_net_DatagramPacketB(InetAddress group) throws Exception {
         String msg = "Hello World";
-        MulticastSocket mss = new MulticastSocket(0);
-        MulticastServer server = new MulticastServer(group, mss.getLocalPort());
-        server.start();
-        Thread.sleep(200);
-        DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg.length(), group, mss.getLocalPort());
-        mss.send(sdp, (byte) 10);
-        Thread.sleep(1000);
-        mss.close();
-        byte[] data = server.rdp.getData();
-        int length = server.rdp.getLength();
-        assertEquals("Failed to send data. Received " + length, msg, new String(data, 0, length));
-        server.stopServer();
+        MulticastSocket sendingSocket = new MulticastSocket(0);
+        MulticastSocket receivingSocket = createReceivingSocket(sendingSocket.getLocalPort());
+        receivingSocket.joinGroup(group);
+
+        InetSocketAddress groupAddress = new InetSocketAddress(group, sendingSocket.getLocalPort());
+        DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+        sendingSocket.send(sdp, (byte) 10 /* ttl */);
+        sendingSocket.close();
+
+        DatagramPacket rdp = createReceiveDatagramPacket();
+        receivingSocket.receive(rdp);
+        String receivedMessage = extractMessage(rdp);
+        assertEquals("Failed to send data. Received " + rdp.getLength(), msg, receivedMessage);
+        receivingSocket.close();
     }
 
     public void test_setInterfaceLjava_net_InetAddress() throws Exception {
         MulticastSocket mss = new MulticastSocket();
         mss.setInterface(InetAddress.getLocalHost());
         InetAddress theInterface = mss.getInterface();
-        // under IPV6 we are not guarrenteed to get the same address back as
-        // the address, all we should be guaranteed is that we get an
-        // address on the same interface
+        // Under IPV6 we are not guaranteed to get the same address back as the address that was
+        // set, all we should be guaranteed is that we get an address on the same interface.
         if (theInterface instanceof Inet6Address) {
-            assertTrue("Failed to return correct interface IPV6", NetworkInterface.getByInetAddress(mss.getInterface()).equals(NetworkInterface.getByInetAddress(theInterface)));
+            assertEquals("Failed to return correct interface IPV6",
+                    NetworkInterface.getByInetAddress(mss.getInterface()),
+                    NetworkInterface.getByInetAddress(theInterface));
         } else {
-            assertTrue("Failed to return correct interface IPV4 got:" + mss.getInterface() + " excpeted: " + InetAddress.getLocalHost(), mss.getInterface().equals(InetAddress.getLocalHost()));
+            assertTrue("Failed to return correct interface IPV4 got:" + mss.getInterface() +
+                    " expected: " + InetAddress.getLocalHost(),
+                    mss.getInterface().equals(InetAddress.getLocalHost()));
         }
         mss.close();
     }
@@ -556,7 +556,7 @@
         test_setInterface_unbound_address(GOOD_IPv6);
     }
 
-    // Regression test for Harmony-2410
+    // Regression test for Harmony-2410.
     private void test_setInterface_unbound_address(InetAddress address) throws Exception {
         MulticastSocket mss = new MulticastSocket();
         try {
@@ -568,7 +568,7 @@
     }
 
     public void test_setNetworkInterfaceLjava_net_NetworkInterface_null() throws Exception {
-        // validate that null interface is handled ok
+        // Validate that null interface is handled ok.
         MulticastSocket mss = new MulticastSocket();
         try {
             mss.setNetworkInterface(null);
@@ -579,10 +579,11 @@
     }
 
     public void test_setNetworkInterfaceLjava_net_NetworkInterface_round_trip() throws Exception {
-        // validate that we can get and set the interface
+        // Validate that we can get and set the interface.
         MulticastSocket mss = new MulticastSocket();
-        mss.setNetworkInterface(networkInterface1);
-        assertEquals("Interface did not seem to be set by setNeworkInterface", networkInterface1, mss.getNetworkInterface());
+        mss.setNetworkInterface(ipv4NetworkInterface);
+        assertEquals("Interface did not seem to be set by setNeworkInterface",
+                ipv4NetworkInterface, mss.getNetworkInterface());
         mss.close();
     }
 
@@ -594,35 +595,35 @@
         test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv6);
     }
 
-    private void test_setNetworkInterfaceLjava_net_NetworkInterface(InetAddress group) throws IOException, InterruptedException {
-        // set up the server and join the group
+    private void test_setNetworkInterfaceLjava_net_NetworkInterface(InetAddress group)
+            throws IOException, InterruptedException {
+        // Set up the receiving socket and join the group.
         Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
         while (theInterfaces.hasMoreElements()) {
             NetworkInterface thisInterface = (NetworkInterface) theInterfaces.nextElement();
             if (thisInterface.getInetAddresses().hasMoreElements() && thisInterface.isUp()) {
                 if ((!(thisInterface.getInetAddresses().nextElement()).isLoopbackAddress())) {
-                    MulticastServer server = new MulticastServer(group, 0);
-                    server.start();
-                    // give the server some time to start up
-                    Thread.sleep(1000);
+                    MulticastSocket receivingSocket = createReceivingSocket(0);
+                    InetSocketAddress groupAddress =
+                            new InetSocketAddress(group, receivingSocket.getLocalPort());
+                    receivingSocket.joinGroup(groupAddress, thisInterface);
 
-                    // Send the packets on a particular interface. The
-                    // source address in the received packet
-                    // should be one of the addresses for the interface
-                    // set
-                    MulticastSocket mss = new MulticastSocket(0);
-                    mss.setNetworkInterface(thisInterface);
+                    // Send the packets on a particular interface. The source address in the
+                    // received packet should be one of the addresses for the interface set.
+                    MulticastSocket sendingSocket = new MulticastSocket(0);
+                    sendingSocket.setNetworkInterface(thisInterface);
                     String msg = thisInterface.getName();
-                    byte theBytes[] = msg.getBytes();
-                    DatagramPacket sdp = new DatagramPacket(theBytes, theBytes.length, group,
-                            server.ms.getLocalPort());
-                    mss.send(sdp);
-                    Thread.sleep(1000);
-                    String receivedMessage = new String(server.rdp.getData(), 0, server.rdp.getLength());
-                    assertEquals("Group member did not recv data sent on a specific interface", msg, receivedMessage);
-                    // stop the server
-                    server.stopServer();
-                    mss.close();
+                    DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+                    sendingSocket.send(sdp);
+
+                    DatagramPacket rdp = createReceiveDatagramPacket();
+                    receivingSocket.receive(rdp);
+                    String receivedMessage = extractMessage(rdp);
+                    assertEquals("Group member did not recv data sent on a specific interface",
+                            msg, receivedMessage);
+                    // Stop the server.
+                    receivingSocket.close();
+                    sendingSocket.close();
                 }
             }
         }
@@ -651,24 +652,28 @@
         assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
         ms.close();
         assertTrue("should be closed", ms.isClosed());
+
         ms = new MulticastSocket(0);
         assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
         ms.close();
         assertTrue("should be closed", ms.isClosed());
+
         ms = new MulticastSocket(0);
         assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
         ms.close();
         assertTrue("should be closed", ms.isClosed());
+
         try {
-            ms = new MulticastSocket(new InetSocketAddress("unresolvedname", 31415));
+            new MulticastSocket(new InetSocketAddress("unresolvedname", 31415));
             fail();
         } catch (IOException expected) {
         }
 
-        // regression test for Harmony-1162
+        // Regression test for Harmony-1162.
         InetSocketAddress addr = new InetSocketAddress("0.0.0.0", 0);
         MulticastSocket s = new MulticastSocket(addr);
         assertTrue(s.getReuseAddress());
+        s.close();
     }
 
     public void test_getLoopbackMode() throws Exception {
@@ -699,129 +704,69 @@
     }
 
     private void test_setLoopbackModeSendReceive(InetAddress group) throws IOException {
+        // Test send receive.
         final String message = "Hello, world!";
 
-        // test send receive
         MulticastSocket socket = new MulticastSocket(0);
         socket.setLoopbackMode(false); // false indicates doing loop back
         socket.joinGroup(group);
 
-        // send the datagram
-        byte[] sendData = message.getBytes();
-        DatagramPacket sendDatagram = new DatagramPacket(sendData, 0, sendData.length,
-                new InetSocketAddress(group, socket.getLocalPort()));
+        // Send the datagram.
+        InetSocketAddress groupAddress = new InetSocketAddress(group, socket.getLocalPort());
+        DatagramPacket sendDatagram = createSendDatagramPacket(groupAddress, message);
         socket.send(sendDatagram);
 
-        // receive the datagram
-        byte[] recvData = new byte[100];
-        DatagramPacket recvDatagram = new DatagramPacket(recvData, recvData.length);
-        socket.setSoTimeout(5000); // prevent eternal block in
+        // Receive the datagram.
+        DatagramPacket recvDatagram = createReceiveDatagramPacket();
+        socket.setSoTimeout(5000); // Prevent eternal block in.
         socket.receive(recvDatagram);
-        String recvMessage = new String(recvData, 0, recvDatagram.getLength());
+        String recvMessage = extractMessage(recvDatagram);
         assertEquals(message, recvMessage);
         socket.close();
     }
 
     public void test_setReuseAddressZ() throws Exception {
-        // test case were we set it to false
-        MulticastSocket theSocket1 = null;
-        MulticastSocket theSocket2 = null;
+        // Test case were we to set ReuseAddress to false.
+        MulticastSocket theSocket1 = new MulticastSocket(null);
+        theSocket1.setReuseAddress(false);
+
+        MulticastSocket theSocket2 = new MulticastSocket(null);
+        theSocket2.setReuseAddress(false);
+
+        InetSocketAddress addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
+        theSocket1.bind(addr);
+        addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
         try {
-            theSocket1 = new MulticastSocket(null);
-            theSocket2 = new MulticastSocket(null);
-            theSocket1.setReuseAddress(false);
-            theSocket2.setReuseAddress(false);
-            InetSocketAddress addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
-            theSocket1.bind(addr);
-            addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
             theSocket2.bind(addr);
-            fail("No exception when trying to connect to do duplicate socket bind with re-useaddr set to false");
+            fail("No exception when trying to connect to do duplicate socket bind with re-useaddr"
+                    + " set to false");
         } catch (BindException expected) {
         }
-        if (theSocket1 != null) {
-            theSocket1.close();
-        }
-        if (theSocket2 != null) {
-            theSocket2.close();
-        }
+        theSocket1.close();
+        theSocket2.close();
 
-        // test case were we set it to true
+        // Test case were we set it to true.
         theSocket1 = new MulticastSocket(null);
         theSocket2 = new MulticastSocket(null);
         theSocket1.setReuseAddress(true);
         theSocket2.setReuseAddress(true);
-        InetSocketAddress addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
+        addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
         theSocket1.bind(addr);
         addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
         theSocket2.bind(addr);
 
-        if (theSocket1 != null) {
-            theSocket1.close();
-        }
-        if (theSocket2 != null) {
-            theSocket2.close();
-        }
+        theSocket1.close();
+        theSocket2.close();
 
-        // test the default case which we expect to be
-        // the same on all platforms
+        // Test the default case which we expect to be the same on all platforms.
         theSocket1 = new MulticastSocket(null);
         theSocket2 = new MulticastSocket(null);
         addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
         theSocket1.bind(addr);
         addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
         theSocket2.bind(addr);
-        if (theSocket1 != null) {
-            theSocket1.close();
-        }
-        if (theSocket2 != null) {
-            theSocket2.close();
-        }
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        // The loopback interface isn't actually useful for sending/receiving multicast messages
-        // but it can be used as a dummy for tests where that does not matter.
-        loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
-        assertNotNull(loopbackInterface);
-        assertTrue(loopbackInterface.isLoopback());
-        assertFalse(loopbackInterface.supportsMulticast());
-
-        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
-
-        // only consider interfaces that have addresses associated with them.
-        // Otherwise tests don't work so well
-        if (interfaces != null) {
-            boolean atLeastOneInterface = false;
-            while (interfaces.hasMoreElements() && (atLeastOneInterface == false)) {
-                networkInterface1 = interfaces.nextElement();
-                if (willWorkForMulticast(networkInterface1)) {
-                    atLeastOneInterface = true;
-                }
-            }
-
-            assertTrue("Test environment must have at least one environment capable of multicast",
-                    atLeastOneInterface);
-
-            // Find the first multicast-compatible interface that supports IPV6 if one exists
-            interfaces = NetworkInterface.getNetworkInterfaces();
-
-            boolean found = false;
-            while (interfaces.hasMoreElements() && !found) {
-                NetworkInterface nextInterface = interfaces.nextElement();
-                if (willWorkForMulticast(nextInterface)) {
-                    Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
-                    while (addresses.hasMoreElements()) {
-                        final InetAddress nextAddress = addresses.nextElement();
-                        if (nextAddress instanceof Inet6Address) {
-                            IPV6networkInterface1 = nextInterface;
-                            found = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
+        theSocket1.close();
+        theSocket2.close();
     }
 
     private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException {
@@ -831,4 +776,26 @@
                 && !iface.isLoopback() && iface.supportsMulticast()
                 && iface.getInetAddresses().hasMoreElements();
     }
+
+    private static MulticastSocket createReceivingSocket(int aPort) throws IOException {
+        MulticastSocket ms = new MulticastSocket(aPort);
+        ms.setSoTimeout(2000);
+        return ms;
+    }
+
+    private static DatagramPacket createReceiveDatagramPacket() {
+        byte[] rbuf = new byte[512];
+        return new DatagramPacket(rbuf, rbuf.length);
+    }
+
+    private static DatagramPacket createSendDatagramPacket(
+            InetSocketAddress groupAndPort, String msg) {
+        return new DatagramPacket(
+                msg.getBytes(), msg.length(), groupAndPort.getAddress(), groupAndPort.getPort());
+    }
+
+    private static String extractMessage(DatagramPacket rdp) {
+        return new String(rdp.getData(), 0, rdp.getLength());
+    }
+
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CurrencyTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CurrencyTest.java
index 092cc54..07256e4 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CurrencyTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/CurrencyTest.java
@@ -28,7 +28,18 @@
 
 public class CurrencyTest extends junit.framework.TestCase {
 
-    private static Locale defaultLocale = Locale.getDefault();
+    private Locale originalLocale;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        originalLocale = Locale.getDefault();
+    }
+
+    @Override
+    protected void tearDown() {
+        Locale.setDefault(originalLocale);
+    }
 
     /**
      * java.util.Currency#getInstance(java.lang.String)
@@ -146,14 +157,16 @@
         assertEquals("currUS.getSymbol()", "$", currUS.getSymbol());
         // END android-changed
 
-        // test what happens if this is an invalid locale,
-        // one with Korean country but an India language
+        // Test what happens if the default is an invalid locale, one with the country Korea (KR)
+        // but a currently unsupported language. "kr" == Kanuri (Korean is actually "ko").
+        // All these values are those defined in the "root" locale or the currency code if one isn't
+        // defined.
         Locale.setDefault(new Locale("kr", "KR"));
         // BEGIN android-changed
         assertEquals("currK.getSymbol()", "\u20a9", currK.getSymbol());
         assertEquals("currI.getSymbol()", "IEP", currI.getSymbol());
+        assertEquals("currUS.getSymbol()", "US$", currUS.getSymbol());
         // END android-changed
-        assertEquals("currUS.getSymbol()", "$", currUS.getSymbol());
     }
 
     /**
@@ -161,7 +174,7 @@
      */
     public void test_getSymbolLjava_util_Locale() {
         //Tests was simplified because java specification not
-        // includes strong requirements for returnig symbol.
+        // includes strong requirements for returning symbol.
         // on android platform used wrong character for yen
         // sign: \u00a5 instead of \uffe5
         Locale[] desiredLocales = new Locale[]{
@@ -243,8 +256,6 @@
             for (i = 0; i < loc1.length; i++) {
                 flag = false;
                 for  (j = 0; j < yen.length; j++) {
-                    byte[] b1 = null;
-                    byte[] b2 = null;
                     if (currJ.getSymbol(loc1[i]).equals(yen[j])) {
                         flag = true;
                         break;
@@ -391,38 +402,4 @@
                     Currency.getInstance(l).toString(), d);
         }
     }
-
-    protected void setUp() {
-        Locale.setDefault(defaultLocale);
-    }
-
-    protected void tearDown() {
-    }
-
-    /**
-     * Helper method to display Currency info
-     *
-     * @param c
-     */
-    private void printCurrency(Currency c) {
-        System.out.println();
-        System.out.println(c.getCurrencyCode());
-        System.out.println(c.getSymbol());
-        System.out.println(c.getDefaultFractionDigits());
-    }
-
-    /**
-     * helper method to display Locale info
-     */
-    private static void printLocale(Locale loc) {
-        System.out.println();
-        System.out.println(loc.getDisplayName());
-        System.out.println(loc.getCountry());
-        System.out.println(loc.getLanguage());
-        System.out.println(loc.getDisplayCountry());
-        System.out.println(loc.getDisplayLanguage());
-        System.out.println(loc.getDisplayName());
-        System.out.println(loc.getISO3Country());
-        System.out.println(loc.getISO3Language());
-    }
 }
diff --git a/include/ScopedIcuLocale.h b/include/ScopedIcuLocale.h
new file mode 100644
index 0000000..2109e03
--- /dev/null
+++ b/include/ScopedIcuLocale.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SCOPED_ICU_LOCALE_H_included
+#define SCOPED_ICU_LOCALE_H_included
+
+#include "JNIHelp.h"
+#include "ScopedUtfChars.h"
+#include "unicode/locid.h"
+
+class ScopedIcuLocale {
+ public:
+  ScopedIcuLocale(JNIEnv* env, jstring javaLocaleName) : mEnv(env) {
+    mLocale.setToBogus();
+
+    if (javaLocaleName == NULL) {
+      jniThrowNullPointerException(mEnv, "javaLocaleName == null");
+      return;
+    }
+
+    const ScopedUtfChars localeName(env, javaLocaleName);
+    if (localeName.c_str() == NULL) {
+      return;
+    }
+
+    mLocale = Locale::createFromName(localeName.c_str());
+  }
+
+  ~ScopedIcuLocale() {
+  }
+
+  bool valid() const {
+    return !mLocale.isBogus();
+  }
+
+  Locale& locale() {
+    return mLocale;
+  }
+
+ private:
+  JNIEnv* const mEnv;
+  Locale mLocale;
+
+  // Disallow copy and assignment.
+  ScopedIcuLocale(const ScopedIcuLocale&);
+  void operator=(const ScopedIcuLocale&);
+};
+
+#endif  // SCOPED_ICU_LOCALE_H_included
diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
index ff52b41..df6b2ce 100644
--- a/libart/src/main/java/java/lang/reflect/AbstractMethod.java
+++ b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
@@ -135,7 +135,7 @@
      *
      * @return the parameter types
      */
-    public Class<?>[] getParameterTypes() {
+    Class<?>[] getParameterTypes() {
         return artMethod.getParameterTypes();
     }
 
diff --git a/libart/src/main/java/java/lang/reflect/Constructor.java b/libart/src/main/java/java/lang/reflect/Constructor.java
index b1efe06..2eb12b0 100644
--- a/libart/src/main/java/java/lang/reflect/Constructor.java
+++ b/libart/src/main/java/java/lang/reflect/Constructor.java
@@ -111,7 +111,7 @@
      * parameter types of this constructor. If the constructor was declared with
      * no parameters, an empty array will be returned.
      */
-    public Class<?>[] getParameterTypes() {
+    @Override public Class<?>[] getParameterTypes() {
         return super.getParameterTypes();
     }
 
diff --git a/libdvm/src/main/java/dalvik/system/VMRuntime.java b/libdvm/src/main/java/dalvik/system/VMRuntime.java
deleted file mode 100644
index 1d58d8d..0000000
--- a/libdvm/src/main/java/dalvik/system/VMRuntime.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dalvik.system;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Provides an interface to VM-global, Dalvik-specific features.
- * An application cannot create its own Runtime instance, and must obtain
- * one from the getRuntime method.
- *
- * @hide
- */
-public final class VMRuntime {
-
-    /**
-     * Holds the VMRuntime singleton.
-     */
-    private static final VMRuntime THE_ONE = new VMRuntime();
-
-    private static final Map<String, String> ABI_TO_INSTRUCTION_SET_MAP
-            = new HashMap<String, String>();
-    static {
-        ABI_TO_INSTRUCTION_SET_MAP.put("armeabi", "arm");
-        ABI_TO_INSTRUCTION_SET_MAP.put("armeabi-v7a", "arm");
-        ABI_TO_INSTRUCTION_SET_MAP.put("mips", "mips");
-        ABI_TO_INSTRUCTION_SET_MAP.put("x86", "x86");
-    }
-
-    private int targetSdkVersion;
-
-    /**
-     * Prevents this class from being instantiated.
-     */
-    private VMRuntime() {
-    }
-
-    /**
-     * Returns the object that represents the VM instance's Dalvik-specific
-     * runtime environment.
-     *
-     * @return the runtime object
-     */
-    public static VMRuntime getRuntime() {
-        return THE_ONE;
-    }
-
-    /**
-     * Returns a copy of the VM's command-line property settings.
-     * These are in the form "name=value" rather than "-Dname=value".
-     */
-    public native String[] properties();
-
-    /**
-     * Returns the VM's boot class path.
-     */
-    public native String bootClassPath();
-
-    /**
-     * Returns the VM's class path.
-     */
-    public native String classPath();
-
-    /**
-     * Returns the VM's version.
-     */
-    public native String vmVersion();
-
-    /**
-     * Returns the name of the shared library providing the VM implementation.
-     */
-    public native String vmLibrary();
-
-    /**
-     * Returns the VM's instruction set.
-     */
-    public String vmInstructionSet() {
-        return "";
-    }
-
-    /**
-     * Returns whether the VM is running in 64-bit mode.
-     */
-    public boolean is64Bit() {
-        return false;
-    }
-
-    /**
-     * Returns whether the VM is running with JNI checking enabled.
-     */
-    public native boolean isCheckJniEnabled();
-
-    /**
-     * Gets the current ideal heap utilization, represented as a number
-     * between zero and one.  After a GC happens, the Dalvik heap may
-     * be resized so that (size of live objects) / (size of heap) is
-     * equal to this number.
-     *
-     * @return the current ideal heap utilization
-     */
-    public native float getTargetHeapUtilization();
-
-    /**
-     * Sets the current ideal heap utilization, represented as a number
-     * between zero and one.  After a GC happens, the Dalvik heap may
-     * be resized so that (size of live objects) / (size of heap) is
-     * equal to this number.
-     *
-     * <p>This is only a hint to the garbage collector and may be ignored.
-     *
-     * @param newTarget the new suggested ideal heap utilization.
-     *                  This value may be adjusted internally.
-     * @return the previous ideal heap utilization
-     * @throws IllegalArgumentException if newTarget is &lt;= 0.0 or &gt;= 1.0
-     */
-    public float setTargetHeapUtilization(float newTarget) {
-        if (newTarget <= 0.0f || newTarget >= 1.0f) {
-            throw new IllegalArgumentException(newTarget +
-                    " out of range (0,1)");
-        }
-        /* Synchronize to make sure that only one thread gets
-         * a given "old" value if both update at the same time.
-         * Allows for reliable save-and-restore semantics.
-         */
-        synchronized (this) {
-            float oldTarget = getTargetHeapUtilization();
-            nativeSetTargetHeapUtilization(newTarget);
-            return oldTarget;
-        }
-    }
-
-    /**
-     * Sets the target SDK version. Should only be called before the
-     * app starts to run, because it may change the VM's behavior in
-     * dangerous ways. Use 0 to mean "current" (since callers won't
-     * necessarily know the actual current SDK version, and the
-     * allocated version numbers start at 1), and 10000 to mean
-     * CUR_DEVELOPMENT.
-     */
-    public synchronized void setTargetSdkVersion(int targetSdkVersion) {
-        this.targetSdkVersion = targetSdkVersion;
-        setTargetSdkVersionNative(this.targetSdkVersion);
-    }
-
-    /**
-     * Gets the target SDK version. See {@link #setTargetSdkVersion} for
-     * special values.
-     */
-    public synchronized int getTargetSdkVersion() {
-        return targetSdkVersion;
-    }
-
-    private native void setTargetSdkVersionNative(int targetSdkVersion);
-
-    /**
-     * This method exists for binary compatibility.  It was part of a
-     * heap sizing API which was removed in Android 3.0 (Honeycomb).
-     */
-    @Deprecated
-    public long getMinimumHeapSize() {
-        return 0;
-    }
-
-    /**
-     * This method exists for binary compatibility.  It was part of a
-     * heap sizing API which was removed in Android 3.0 (Honeycomb).
-     */
-    @Deprecated
-    public long setMinimumHeapSize(long size) {
-        return 0;
-    }
-
-    /**
-     * This method exists for binary compatibility.  It used to
-     * perform a garbage collection that cleared SoftReferences.
-     */
-    @Deprecated
-    public void gcSoftReferences() {}
-
-    /**
-     * This method exists for binary compatibility.  It is equivalent
-     * to {@link System#runFinalization}.
-     */
-    @Deprecated
-    public void runFinalizationSync() {
-        System.runFinalization();
-    }
-
-    /**
-     * Implements setTargetHeapUtilization().
-     *
-     * @param newTarget the new suggested ideal heap utilization.
-     *                  This value may be adjusted internally.
-     */
-    private native void nativeSetTargetHeapUtilization(float newTarget);
-
-    /**
-     * This method exists for binary compatibility.  It was part of
-     * the external allocation API which was removed in Android 3.0 (Honeycomb).
-     */
-    @Deprecated
-    public boolean trackExternalAllocation(long size) {
-        return true;
-    }
-
-    /**
-     * This method exists for binary compatibility.  It was part of
-     * the external allocation API which was removed in Android 3.0 (Honeycomb).
-     */
-    @Deprecated
-    public void trackExternalFree(long size) {}
-
-    /**
-     * This method exists for binary compatibility.  It was part of
-     * the external allocation API which was removed in Android 3.0 (Honeycomb).
-     */
-    @Deprecated
-    public long getExternalBytesAllocated() {
-        return 0;
-    }
-
-    /**
-     * Tells the VM to enable the JIT compiler. If the VM does not have a JIT
-     * implementation, calling this method should have no effect.
-     */
-    public native void startJitCompilation();
-
-    /**
-     * Tells the VM to disable the JIT compiler. If the VM does not have a JIT
-     * implementation, calling this method should have no effect.
-     */
-    public native void disableJitCompilation();
-
-    /**
-     * Returns an array allocated in an area of the Java heap where it will never be moved.
-     * This is used to implement native allocations on the Java heap, such as DirectByteBuffers
-     * and Bitmaps.
-     */
-    public native Object newNonMovableArray(Class<?> componentType, int length);
-
-    /**
-     * Returns an array of at least minLength, but potentially larger. The increased size comes from
-     * avoiding any padding after the array. The amount of padding varies depending on the
-     * componentType and the memory allocator implementation.
-     */
-    public Object newUnpaddedArray(Class<?> componentType, int minLength) {
-        // Dalvik has 32bit pointers, the array header is 16bytes plus 4bytes for dlmalloc,
-        // allocations are 8byte aligned so having 4bytes of array data avoids padding.
-        if (!componentType.isPrimitive()) {
-            int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
-            return java.lang.reflect.Array.newInstance(componentType, size);
-        } else if (componentType == char.class) {
-            int bytes = 20 + (2 * minLength);
-            int alignedUpBytes = (bytes + 7) & -8;
-            int dataBytes = alignedUpBytes - 20;
-            int size = dataBytes / 2;
-            return new char[size];
-        } else if (componentType == int.class) {
-            int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
-            return new int[size];
-        } else if (componentType == byte.class) {
-            int bytes = 20 + minLength;
-            int alignedUpBytes = (bytes + 7) & -8;
-            int dataBytes = alignedUpBytes - 20;
-            int size = dataBytes;
-            return new byte[size];
-        } else if (componentType == boolean.class) {
-            int bytes = 20 + minLength;
-            int alignedUpBytes = (bytes + 7) & -8;
-            int dataBytes = alignedUpBytes - 20;
-            int size = dataBytes;
-            return new boolean[size];
-        } else if (componentType == short.class) {
-            int bytes = 20 + (2 * minLength);
-            int alignedUpBytes = (bytes + 7) & -8;
-            int dataBytes = alignedUpBytes - 20;
-            int size = dataBytes / 2;
-            return new short[size];
-        } else if (componentType == float.class) {
-            int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
-            return new float[size];
-        } else if (componentType == long.class) {
-            return new long[minLength];
-        } else if (componentType == double.class) {
-            return new double[minLength];
-        } else {
-            assert componentType == void.class;
-            throw new IllegalArgumentException("Can't allocate an array of void");
-        }
-    }
-
-    /**
-     * Returns the address of array[0]. This differs from using JNI in that JNI might lie and
-     * give you the address of a copy of the array when in forcecopy mode.
-     */
-    public native long addressOf(Object array);
-
-    /**
-     * Removes any growth limits, allowing the application to allocate
-     * up to the maximum heap size.
-     */
-    public native void clearGrowthLimit();
-
-    /**
-     * Returns true if either a Java debugger or native debugger is active.
-     */
-    public native boolean isDebuggerActive();
-
-    /**
-     * Registers a native allocation so that the heap knows about it and performs GC as required.
-     * If the number of native allocated bytes exceeds the native allocation watermark, the
-     * function requests a concurrent GC. If the native bytes allocated exceeds a second higher
-     * watermark, it is determined that the application is registering native allocations at an
-     * unusually high rate and a GC is performed inside of the function to prevent memory usage
-     * from excessively increasing.
-     */
-    public native void registerNativeAllocation(int bytes);
-
-    /**
-     * Registers a native free by reducing the number of native bytes accounted for.
-     */
-    public native void registerNativeFree(int bytes);
-
-    /**
-     * Let the heap know of the new process state. This can change allocation and garbage collection
-     * behavior regarding trimming and compaction.
-     */
-    public native void updateProcessState(int state);
-
-    /**
-     * Fill in dex caches with classes, fields, and methods that are
-     * already loaded. Typically used after Zygote preloading.
-     */
-    public native void preloadDexCaches();
-
-    /**
-     * Register application info
-     */
-    public static void registerAppInfo(String appDir, String processName, String pkgname) {
-        // Nothing to do in dalvik.
-    }
-
-    /**
-     * Returns the runtime instruction set corresponding to a given ABI. Multiple
-     * compatible ABIs might map to the same instruction set. For example
-     * {@code armeabi-v7a} and {@code armeabi} might map to the instruction set {@code arm}.
-     *
-     * This influences the compilation of the applications classes.
-     */
-    public static String getInstructionSet(String abi) {
-        final String instructionSet = ABI_TO_INSTRUCTION_SET_MAP.get(abi);
-        if (instructionSet == null) {
-            throw new IllegalArgumentException("Unsupported ABI: " + abi);
-        }
-
-        return instructionSet;
-    }
-}
diff --git a/libdvm/src/main/java/dalvik/system/VMStack.java b/libdvm/src/main/java/dalvik/system/VMStack.java
deleted file mode 100644
index bae1829..0000000
--- a/libdvm/src/main/java/dalvik/system/VMStack.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dalvik.system;
-
-/**
- * Provides a limited interface to the Dalvik VM stack. This class is mostly
- * used for implementing security checks.
- *
- * @hide
- */
-public final class VMStack {
-    /**
-     * Returns the defining class loader of the caller's caller.
-     *
-     * @return the requested class loader, or {@code null} if this is the
-     *         bootstrap class loader.
-     */
-    native public static ClassLoader getCallingClassLoader();
-
-    /**
-     * Returns the class of the caller's caller's caller.
-     *
-     * @return the requested class, or {@code null}.
-     */
-    native public static Class<?> getStackClass2();
-
-    /**
-     * Creates an array of classes from the methods at the top of the stack.
-     * We continue until we reach the bottom of the stack or exceed the
-     * specified maximum depth.
-     * <p>
-     * The topmost stack frame (this method) and the one above that (the
-     * caller) are excluded from the array.  Frames with java.lang.reflect
-     * classes are skipped over.
-     * <p>
-     * The classes in the array are the defining classes of the methods.
-     * <p>
-     * This is similar to Harmony's VMStack.getClasses, except that this
-     * implementation doesn't have a concept of "privileged" frames.
-     *
-     * @param maxDepth
-     *      maximum number of classes to return, or -1 for all
-     * @return an array with classes for the most-recent methods on the stack
-     */
-    native public static Class<?>[] getClasses(int maxDepth);
-
-    /**
-     * Returns the first ClassLoader on the call stack that isn't either of
-     * the passed-in ClassLoaders.
-     */
-    public static ClassLoader getClosestUserClassLoader(ClassLoader bootstrap,
-                                                        ClassLoader system) {
-        Class<?>[] stackClasses = VMStack.getClasses(-1);
-        for (Class<?> stackClass : stackClasses) {
-            ClassLoader loader = stackClass.getClassLoader();
-            if (loader != null && loader != bootstrap && loader != system) {
-                return loader;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Retrieves the stack trace from the specified thread.
-     *
-     * @param t
-     *      thread of interest
-     * @return an array of stack trace elements, or null if the thread
-     *      doesn't have a stack trace (e.g. because it exited)
-     */
-    native public static StackTraceElement[] getThreadStackTrace(Thread t);
-
-    /**
-     * Retrieves a partial stack trace from the specified thread into
-     * the provided array.
-     *
-     * @param t
-     *      thread of interest
-     * @param stackTraceElements
-     *      preallocated array for use when only the top of stack is
-     *      desired. Unused elements will be filled with null values.
-     * @return the number of elements filled
-     */
-    native public static int fillStackTraceElements(Thread t,
-        StackTraceElement[] stackTraceElements);
-}
diff --git a/libdvm/src/main/java/java/lang/Class.java b/libdvm/src/main/java/java/lang/Class.java
deleted file mode 100644
index af6278d..0000000
--- a/libdvm/src/main/java/java/lang/Class.java
+++ /dev/null
@@ -1,1354 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Copyright (C) 2006-2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import com.android.dex.Dex;
-import dalvik.system.VMStack;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.Inherited;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.GenericDeclaration;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.net.URL;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import org.apache.harmony.kernel.vm.StringUtils;
-import libcore.reflect.AnnotationAccess;
-import libcore.reflect.GenericSignatureParser;
-import libcore.reflect.InternalNames;
-import libcore.reflect.Types;
-import libcore.util.BasicLruCache;
-import libcore.util.CollectionUtils;
-import libcore.util.EmptyArray;
-
-/**
- * The in-memory representation of a Java class. This representation serves as
- * the starting point for querying class-related information, a process usually
- * called "reflection". There are basically three types of {@code Class}
- * instances: those representing real classes and interfaces, those representing
- * primitive types, and those representing array classes.
- *
- * <h4>Class instances representing object types (classes or interfaces)</h4>
- * <p>
- * These represent an ordinary class or interface as found in the class
- * hierarchy. The name associated with these {@code Class} instances is simply
- * the fully qualified class name of the class or interface that it represents.
- * In addition to this human-readable name, each class is also associated by a
- * so-called <em>signature</em>, which is the letter "L", followed by the
- * class name and a semicolon (";"). The signature is what the runtime system
- * uses internally for identifying the class (for example in a DEX file).
- * </p>
- * <h4>Classes representing primitive types</h4>
- * <p>
- * These represent the standard Java primitive types and hence share their
- * names (for example "int" for the {@code int} primitive type). Although it is
- * not possible to create new instances based on these {@code Class} instances,
- * they are still useful for providing reflection information, and as the
- * component type of array classes. There is one {@code Class} instance for each
- * primitive type, and their signatures are:
- * </p>
- * <ul>
- * <li>{@code B} representing the {@code byte} primitive type</li>
- * <li>{@code S} representing the {@code short} primitive type</li>
- * <li>{@code I} representing the {@code int} primitive type</li>
- * <li>{@code J} representing the {@code long} primitive type</li>
- * <li>{@code F} representing the {@code float} primitive type</li>
- * <li>{@code D} representing the {@code double} primitive type</li>
- * <li>{@code C} representing the {@code char} primitive type</li>
- * <li>{@code Z} representing the {@code boolean} primitive type</li>
- * <li>{@code V} representing void function return values</li>
- * </ul>
- * <p>
- * <h4>Classes representing array classes</h4>
- * <p>
- * These represent the classes of Java arrays. There is one such {@code Class}
- * instance per combination of array leaf component type and arity (number of
- * dimensions). In this case, the name associated with the {@code Class}
- * consists of one or more left square brackets (one per dimension in the array)
- * followed by the signature of the class representing the leaf component type,
- * which can be either an object type or a primitive type. The signature of a
- * {@code Class} representing an array type is the same as its name. Examples
- * of array class signatures are:
- * </p>
- * <ul>
- * <li>{@code [I} representing the {@code int[]} type</li>
- * <li>{@code [Ljava/lang/String;} representing the {@code String[]} type</li>
- * <li>{@code [[[C} representing the {@code char[][][]} type (three dimensions!)</li>
- * </ul>
- */
-public final class Class<T> implements Serializable, AnnotatedElement, GenericDeclaration, Type {
-
-    private static final long serialVersionUID = 3206093459760846163L;
-
-    /**
-     * Class def index from dex file. An index of -1 indicates that there is no class definition,
-     * for example for an array type.
-     */
-    private transient int dexClassDefIndex;
-
-    /** The type index of this class within the dex file that defines it. */
-    private transient int dexTypeIndex;
-
-    /**
-     * Have we computed the type and class def indices? Volatile to avoid double check locking bugs.
-     */
-    private transient volatile boolean dexIndicesInitialized;
-
-    /**
-     * Lazily computed name of this class; always prefer calling getName().
-     */
-    private transient String name;
-
-    private Class() {
-        // Prevent this class to be instantiated, instance
-        // should be created by JVM only
-    }
-
-    /**
-     * Returns the dex file from which this class was loaded.
-     * @hide
-     */
-    public native Dex getDex();
-
-    /** Lazily compute indices in to Dex */
-    private synchronized void computeDexIndices() {
-        if (!dexIndicesInitialized) {
-            Dex dex = getDex();
-            dexTypeIndex = dex.findTypeIndex(InternalNames.getInternalName(this));
-            if (dexTypeIndex < 0) {
-                dexTypeIndex = -1;
-                dexClassDefIndex = -1;
-            } else {
-                dexClassDefIndex = dex.findClassDefIndexFromTypeIndex(dexTypeIndex);
-            }
-            dexIndicesInitialized = true;
-        }
-    }
-
-    /**
-     * The class def of this class in its own Dex, or -1 if there is no class def.
-     *
-     * @hide
-     */
-    public int getDexClassDefIndex() {
-        if (!dexIndicesInitialized) {
-            computeDexIndices();
-        }
-        return dexClassDefIndex;
-    }
-
-    /**
-     * The type index of this class in its own Dex, or -1 if it is unknown. If a class is referenced
-     * by multiple Dex files, it will have a different type index in each. Dex files support 65534
-     * type indices, with 65535 representing no index.
-     *
-     * @hide
-     */
-    public int getDexTypeIndex() {
-        if (!dexIndicesInitialized) {
-            computeDexIndices();
-        }
-        return dexTypeIndex;
-    }
-
-    /**
-     * Returns a {@code Class} object which represents the class with the
-     * given name. The name should be the name of a non-primitive class, as described in
-     * the {@link Class class definition}.
-     * Primitive types can not be found using this method; use {@code int.class} or {@code Integer.TYPE} instead.
-     *
-     * <p>If the class has not yet been loaded, it is loaded and initialized
-     * first. This is done through either the class loader of the calling class
-     * or one of its parent class loaders. It is possible that a static initializer is run as
-     * a result of this call.
-     *
-     * @throws ClassNotFoundException
-     *             if the requested class can not be found.
-     * @throws LinkageError
-     *             if an error occurs during linkage
-     * @throws ExceptionInInitializerError
-     *             if an exception occurs during static initialization of a
-     *             class.
-     */
-    public static Class<?> forName(String className) throws ClassNotFoundException {
-        return forName(className, true, VMStack.getCallingClassLoader());
-    }
-
-    /**
-     * Returns a {@code Class} object which represents the class with the
-     * given name. The name should be the name of a non-primitive class, as described in
-     * the {@link Class class definition}.
-     * Primitive types can not be found using this method; use {@code int.class} or {@code Integer.TYPE} instead.
-     *
-     * <p>If the class has not yet been loaded, it is loaded first, using the given class loader.
-     * If the class has not yet been initialized and {@code shouldInitialize} is true,
-     * the class will be initialized.
-     *
-     * @throws ClassNotFoundException
-     *             if the requested class can not be found.
-     * @throws LinkageError
-     *             if an error occurs during linkage
-     * @throws ExceptionInInitializerError
-     *             if an exception occurs during static initialization of a
-     *             class.
-     */
-    public static Class<?> forName(String className, boolean shouldInitialize,
-            ClassLoader classLoader) throws ClassNotFoundException {
-
-        if (classLoader == null) {
-            classLoader = ClassLoader.getSystemClassLoader();
-        }
-        // Catch an Exception thrown by the underlying native code. It wraps
-        // up everything inside a ClassNotFoundException, even if e.g. an
-        // Error occurred during initialization. This as a workaround for
-        // an ExceptionInInitializerError that's also wrapped. It is actually
-        // expected to be thrown. Maybe the same goes for other errors.
-        // Not wrapping up all the errors will break android though.
-        Class<?> result;
-        try {
-            result = classForName(className, shouldInitialize,
-                    classLoader);
-        } catch (ClassNotFoundException e) {
-            Throwable cause = e.getCause();
-            if (cause instanceof ExceptionInInitializerError) {
-                throw (ExceptionInInitializerError) cause;
-            }
-            throw e;
-        }
-        return result;
-    }
-
-    private static native Class<?> classForName(String className, boolean shouldInitialize,
-            ClassLoader classLoader) throws ClassNotFoundException;
-
-    /**
-     * Returns an array containing {@code Class} objects for all public classes
-     * and interfaces that are members of this class. This includes public
-     * members inherited from super classes and interfaces. If there are no such
-     * class members or if this object represents a primitive type then an array
-     * of length 0 is returned.
-     */
-    public Class<?>[] getClasses() {
-        Class<?>[] result = getDeclaredClasses(this, true);
-        // Traverse all superclasses.
-        for (Class<?> c = this.getSuperclass(); c != null; c = c.getSuperclass()) {
-            Class<?>[] temp = getDeclaredClasses(c, true);
-            if (temp.length != 0) {
-                result = arraycopy(new Class[result.length + temp.length], result, temp);
-            }
-        }
-        return result;
-    }
-
-    @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-
-        A annotation = getDeclaredAnnotation(annotationType);
-        if (annotation != null) {
-            return annotation;
-        }
-
-        if (annotationType.isAnnotationPresent(Inherited.class)) {
-            for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
-                annotation = sup.getDeclaredAnnotation(annotationType);
-                if (annotation != null) {
-                    return annotation;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns an array containing all the annotations of this class. If there are no annotations
-     * then an empty array is returned.
-     *
-     * @see #getDeclaredAnnotations()
-     */
-    public Annotation[] getAnnotations() {
-        /*
-         * We need to get the annotations declared on this class, plus the
-         * annotations from superclasses that have the "@Inherited" annotation
-         * set.  We create a temporary map to use while we accumulate the
-         * annotations and convert it to an array at the end.
-         *
-         * It's possible to have duplicates when annotations are inherited.
-         * We use a Map to filter those out.
-         *
-         * HashMap might be overkill here.
-         */
-        HashMap<Class, Annotation> map = new HashMap<Class, Annotation>();
-        Annotation[] declaredAnnotations = getDeclaredAnnotations();
-
-        for (int i = declaredAnnotations.length-1; i >= 0; --i) {
-            map.put(declaredAnnotations[i].annotationType(), declaredAnnotations[i]);
-        }
-        for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
-            declaredAnnotations = sup.getDeclaredAnnotations();
-            for (int i = declaredAnnotations.length-1; i >= 0; --i) {
-                Class<?> clazz = declaredAnnotations[i].annotationType();
-                if (!map.containsKey(clazz) && clazz.isAnnotationPresent(Inherited.class)) {
-                    map.put(clazz, declaredAnnotations[i]);
-                }
-            }
-        }
-
-        /* convert annotation values from HashMap to array */
-        Collection<Annotation> coll = map.values();
-        return coll.toArray(new Annotation[coll.size()]);
-    }
-
-    /**
-     * Returns the canonical name of this class. If this class does not have a
-     * canonical name as defined in the Java Language Specification, then the
-     * method returns {@code null}.
-     */
-    public String getCanonicalName() {
-        if (isLocalClass() || isAnonymousClass())
-            return null;
-
-        if (isArray()) {
-            /*
-             * The canonical name of an array type depends on the (existence of)
-             * the component type's canonical name.
-             */
-            String name = getComponentType().getCanonicalName();
-            if (name != null) {
-                return name + "[]";
-            }
-        } else if (isMemberClass()) {
-            /*
-             * The canonical name of an inner class depends on the (existence
-             * of) the declaring class' canonical name.
-             */
-            String name = getDeclaringClass().getCanonicalName();
-            if (name != null) {
-                return name + "." + getSimpleName();
-            }
-        } else {
-            /*
-             * The canonical name of a top-level class or primitive type is
-             * equal to the fully qualified name.
-             */
-            return getName();
-        }
-
-        /*
-         * Other classes don't have a canonical name.
-         */
-        return null;
-    }
-
-    /**
-     * Returns the class loader which was used to load the class represented by
-     * this {@code Class}. Implementations are free to return {@code null} for
-     * classes that were loaded by the bootstrap class loader. The Android
-     * reference implementation, though, always returns a reference to an actual
-     * class loader.
-     */
-    public ClassLoader getClassLoader() {
-        if (this.isPrimitive()) {
-            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 = getClassLoader(this);
-        return loader == null ? BootClassLoader.getInstance() : loader;
-    }
-
-    /*
-     * Returns the defining class loader for the given class.
-     */
-    private static native ClassLoader getClassLoader(Class<?> c);
-
-    /**
-     * Returns a {@code Class} object which represents the component type if
-     * this class represents an array type. Returns {@code null} if this class
-     * does not represent an array type. The component type of an array type is
-     * the type of the elements of the array.
-     */
-    public native Class<?> getComponentType();
-
-    /**
-     * Returns a {@code Constructor} object which represents the public
-     * constructor matching the given parameter types.
-     * {@code (Class[]) null} is equivalent to the empty array.
-     *
-     * <p>See {@link #getMethod} for details of the search order.
-     * Use {@link #getDeclaredConstructor} if you don't want to search superclasses.
-     *
-     * @throws NoSuchMethodException
-     *             if the constructor can not be found.
-     */
-    @SuppressWarnings("unchecked")
-    public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException {
-        return (Constructor) getConstructorOrMethod("<init>", false, true, parameterTypes);
-    }
-
-    /**
-     * Returns a constructor or method with the given name. Use "<init>" to return a constructor.
-     */
-    private Member getConstructorOrMethod(String name, boolean searchSuperTypes,
-            boolean publicOnly, Class<?>[] parameterTypes) throws NoSuchMethodException {
-        if (searchSuperTypes && !publicOnly) {
-            throw new AssertionError(); // can't lookup non-public members recursively
-        }
-        if (name == null) {
-            throw new NullPointerException("name == null");
-        }
-        if (parameterTypes == null) {
-            parameterTypes = EmptyArray.CLASS;
-        }
-        for (Class<?> c : parameterTypes) {
-            if (c == null) {
-                throw new NoSuchMethodException("parameter type is null");
-            }
-        }
-        Member result = searchSuperTypes
-                ? getPublicConstructorOrMethodRecursive(name, parameterTypes)
-                : Class.getDeclaredConstructorOrMethod(this, name, parameterTypes);
-        if (result == null || publicOnly && (result.getModifiers() & Modifier.PUBLIC) == 0) {
-            throw new NoSuchMethodException(name + " " + Arrays.toString(parameterTypes));
-        }
-        return result;
-    }
-
-    private Member getPublicConstructorOrMethodRecursive(String name, Class<?>[] parameterTypes) {
-        // search superclasses
-        for (Class<?> c = this; c != null; c = c.getSuperclass()) {
-            Member result = Class.getDeclaredConstructorOrMethod(c, name, parameterTypes);
-            if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
-                return result;
-            }
-        }
-
-        // search implemented interfaces
-        for (Class<?> c = this; c != null; c = c.getSuperclass()) {
-            for (Class<?> ifc : c.getInterfaces()) {
-                Member result = ifc.getPublicConstructorOrMethodRecursive(name, parameterTypes);
-                if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
-                    return result;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns an array containing {@code Constructor} objects for all public
-     * constructors for this {@code Class}. If there
-     * are no public constructors or if this {@code Class} represents an array
-     * class, a primitive type or void then an empty array is returned.
-     *
-     * @see #getDeclaredConstructors()
-     */
-    public Constructor<?>[] getConstructors() {
-        return getDeclaredConstructors(this, true);
-    }
-
-    /**
-     * Returns the annotations that are directly defined on the class
-     * represented by this {@code Class}. Annotations that are inherited are not
-     * included in the result. If there are no annotations at all, an empty
-     * array is returned.
-     *
-     * @see #getAnnotations()
-     */
-    public native Annotation[] getDeclaredAnnotations();
-
-    /**
-     * Returns the annotation if it exists.
-     */
-    native private <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass);
-
-    /**
-     * Returns true if the annotation exists.
-     */
-    native private boolean isDeclaredAnnotationPresent(Class<? extends Annotation> annotationClass);
-
-    /**
-     * Returns an array containing {@code Class} objects for all classes and
-     * interfaces that are declared as members of the class which this {@code
-     * Class} represents. If there are no classes or interfaces declared or if
-     * this class represents an array class, a primitive type or void, then an
-     * empty array is returned.
-     */
-    public Class<?>[] getDeclaredClasses() {
-        return getDeclaredClasses(this, false);
-    }
-
-    /*
-     * Returns the list of member classes of the given class.
-     * If no members exist, an empty array is returned.
-     */
-    private static native Class<?>[] getDeclaredClasses(Class<?> c, boolean publicOnly);
-
-    /**
-     * Returns a {@code Constructor} object which represents the constructor
-     * matching the given parameter types that is declared by the class
-     * represented by this {@code Class}.
-     * {@code (Class[]) null} is equivalent to the empty array.
-     *
-     * <p>Use {@link #getConstructor} if you want to search superclasses.
-     *
-     * @throws NoSuchMethodException
-     *             if the requested constructor can not be found.
-     */
-    @SuppressWarnings("unchecked")
-    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
-            throws NoSuchMethodException {
-        return (Constructor) getConstructorOrMethod("<init>", false, false, parameterTypes);
-    }
-
-    /**
-     * Returns an array containing {@code Constructor} objects for all
-     * constructors declared in the class represented by this {@code Class}. If
-     * there are no constructors or if this {@code Class} represents an array
-     * class, a primitive type, or void then an empty array is returned.
-     *
-     * @see #getConstructors()
-     */
-    public Constructor<?>[] getDeclaredConstructors() {
-        return getDeclaredConstructors(this, false);
-    }
-
-    /*
-     * Returns the list of constructors. If no constructors exist, an empty array is returned.
-     */
-    private static native <T> Constructor<T>[] getDeclaredConstructors(Class<T> c,
-                                                                       boolean publicOnly);
-
-    /**
-     * Returns a {@code Field} object for the field with the given name
-     * which is declared in the class represented by this {@code Class}.
-     *
-     * @throws NoSuchFieldException if the requested field can not be found.
-     * @see #getField(String)
-     */
-    public Field getDeclaredField(String name) throws NoSuchFieldException {
-        if (name == null) {
-            throw new NullPointerException("name == null");
-        }
-        Field result = getDeclaredField(this, name);
-        if (result == null) {
-            throw new NoSuchFieldException(name);
-        }
-        return result;
-    }
-
-    /**
-     * Returns an array containing {@code Field} objects for all fields declared
-     * in the class represented by this {@code Class}. If there are no fields or
-     * if this {@code Class} represents an array class, a primitive type or void
-     * then an empty array is returned.
-     *
-     * @see #getFields()
-     */
-    public Field[] getDeclaredFields() {
-        return getDeclaredFields(this, false);
-    }
-
-    /*
-     * Returns the list of fields without performing any security checks
-     * first. If no fields exist at all, an empty array is returned.
-     */
-    static native Field[] getDeclaredFields(Class<?> c, boolean publicOnly);
-
-    /**
-     * Returns the field if it is defined by {@code c}; null otherwise. This
-     * may return a non-public member.
-     */
-    static native Field getDeclaredField(Class<?> c, String name);
-
-    /**
-     * Returns a {@code Method} object which represents the method matching the
-     * given name and parameter types that is declared by the class
-     * represented by this {@code Class}.
-     * {@code (Class[]) null} is equivalent to the empty array.
-     *
-     * <p>See {@link #getMethod} if you want to search superclasses.
-     *
-     * @throws NoSuchMethodException
-     *             if the requested method can not be found.
-     * @throws NullPointerException
-     *             if {@code name} is {@code null}.
-     */
-    public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
-            throws NoSuchMethodException {
-        Member member = getConstructorOrMethod(name, false, false, parameterTypes);
-        if (member instanceof Constructor) {
-            throw new NoSuchMethodException(name);
-        }
-        return (Method) member;
-    }
-
-    /**
-     * Returns an array containing {@code Method} objects for all methods
-     * declared in the class represented by this {@code Class}. If there are no
-     * methods or if this {@code Class} represents an array class, a primitive
-     * type or void then an empty array is returned.
-     *
-     * @see #getMethods()
-     */
-    public Method[] getDeclaredMethods() {
-        return getDeclaredMethods(this, false);
-    }
-
-    /**
-     * Returns the list of methods. If no methods exist, an empty array is returned.
-     */
-    static native Method[] getDeclaredMethods(Class<?> c, boolean publicOnly);
-
-    /**
-     * Returns the constructor or method if it is defined by {@code c}; null
-     * otherwise. This may return a non-public member. Use "<init>" to get a constructor.
-     */
-    static native Member getDeclaredConstructorOrMethod(Class c, String name, Class[] args);
-
-    /**
-     * Returns the declaring {@code Class} of this {@code Class}. Returns
-     * {@code null} if the class is not a member of another class or if this
-     * {@code Class} represents an array class, a primitive type, or void.
-     */
-    public native Class<?> getDeclaringClass();
-
-    /**
-     * Returns the enclosing {@code Class} of this {@code Class}. If there is no
-     * enclosing class the method returns {@code null}.
-     */
-    public native Class<?> getEnclosingClass();
-
-    /**
-     * Returns the enclosing {@code Constructor} of this {@code Class}, if it is an
-     * anonymous or local/automatic class; otherwise {@code null}.
-     */
-    public native Constructor<?> getEnclosingConstructor();
-
-    /**
-     * Returns the enclosing {@code Method} of this {@code Class}, if it is an
-     * anonymous or local/automatic class; otherwise {@code null}.
-     */
-    public native Method getEnclosingMethod();
-
-    /**
-     * Returns the {@code enum} constants associated with this {@code Class}.
-     * Returns {@code null} if this {@code Class} does not represent an {@code
-     * enum} type.
-     */
-    @SuppressWarnings("unchecked") // we only cast after confirming that this class is an enum
-    public T[] getEnumConstants() {
-        if (!isEnum()) {
-            return null;
-        }
-        return (T[]) Enum.getSharedConstants((Class) this).clone();
-    }
-
-    /**
-     * Returns a {@code Field} object which represents the public field with the
-     * given name. This method first searches the class C represented by
-     * this {@code Class}, then the interfaces implemented by C and finally the
-     * superclasses of C.
-     *
-     * @throws NoSuchFieldException
-     *             if the field can not be found.
-     * @see #getDeclaredField(String)
-     */
-    public Field getField(String name) throws NoSuchFieldException {
-        if (name == null) {
-            throw new NullPointerException("name == null");
-        }
-        Field result = getPublicFieldRecursive(name);
-        if (result == null) {
-            throw new NoSuchFieldException(name);
-        }
-        return result;
-    }
-
-    private Field getPublicFieldRecursive(String name) {
-        // search superclasses
-        for (Class<?> c = this; c != null; c = c.getSuperclass()) {
-            Field result = Class.getDeclaredField(c, name);
-            if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
-                return result;
-            }
-        }
-
-        // search implemented interfaces
-        for (Class<?> c = this; c != null; c = c.getSuperclass()) {
-            for (Class<?> ifc : c.getInterfaces()) {
-                Field result = ifc.getPublicFieldRecursive(name);
-                if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
-                    return result;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns an array containing {@code Field} objects for all public fields
-     * for the class C represented by this {@code Class}. Fields may be declared
-     * in C, the interfaces it implements or in the superclasses of C. The
-     * elements in the returned array are in no particular order.
-     *
-     * <p>If there are no public fields or if this class represents an array class,
-     * a primitive type or {@code void} then an empty array is returned.
-     *
-     * @see #getDeclaredFields()
-     */
-    public Field[] getFields() {
-        List<Field> fields = new ArrayList<Field>();
-        getPublicFieldsRecursive(fields);
-
-        /*
-         * The result may include duplicates when this class implements an interface
-         * through multiple paths. Remove those duplicates.
-         */
-        CollectionUtils.removeDuplicates(fields, Field.ORDER_BY_NAME_AND_DECLARING_CLASS);
-        return fields.toArray(new Field[fields.size()]);
-    }
-
-    /**
-     * Populates {@code result} with public fields defined by this class, its
-     * superclasses, and all implemented interfaces.
-     */
-    private void getPublicFieldsRecursive(List<Field> result) {
-        // search superclasses
-        for (Class<?> c = this; c != null; c = c.getSuperclass()) {
-            for (Field field : Class.getDeclaredFields(c, true)) {
-                result.add(field);
-            }
-        }
-
-        // search implemented interfaces
-        for (Class<?> c = this; c != null; c = c.getSuperclass()) {
-            for (Class<?> ifc : c.getInterfaces()) {
-                ifc.getPublicFieldsRecursive(result);
-            }
-        }
-    }
-
-    /**
-     * Returns the {@link Type}s of the interfaces that this {@code Class} directly
-     * implements. If the {@code Class} represents a primitive type or {@code
-     * void} then an empty array is returned.
-     */
-    public Type[] getGenericInterfaces() {
-        Type[] result;
-        synchronized (Caches.genericInterfaces) {
-            result = Caches.genericInterfaces.get(this);
-            if (result == null) {
-                String annotationSignature = AnnotationAccess.getSignature(this);
-                if (annotationSignature == null) {
-                    result = getInterfaces();
-                } else {
-                    GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
-                    parser.parseForClass(this, annotationSignature);
-                    result = Types.getTypeArray(parser.interfaceTypes, false);
-                }
-                Caches.genericInterfaces.put(this, result);
-            }
-        }
-        return (result.length == 0) ? result : result.clone();
-    }
-
-    /**
-     * Returns the {@code Type} that represents the superclass of this {@code
-     * class}.
-     */
-    public Type getGenericSuperclass() {
-        Type genericSuperclass = getSuperclass();
-        // This method is specified to return null for all cases where getSuperclass
-        // returns null, i.e, for primitives, interfaces, void and java.lang.Object.
-
-        if (genericSuperclass == null) {
-            return null;
-        }
-        String annotationSignature = AnnotationAccess.getSignature(this);
-        if (annotationSignature != null) {
-            GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
-            parser.parseForClass(this, annotationSignature);
-            genericSuperclass = parser.superclassType;
-        }
-        return Types.getType(genericSuperclass);
-    }
-
-    /**
-     * Returns an array of {@code Class} objects that match the interfaces
-     * in the {@code implements} declaration of the class represented
-     * by this {@code Class}. The order of the elements in the array is
-     * identical to the order in the original class declaration. If the class
-     * does not implement any interfaces, an empty array is returned.
-     */
-    public native Class<?>[] getInterfaces();
-
-    /**
-     * Returns a {@code Method} object which represents the public method with
-     * the given name and parameter types.
-     * {@code (Class[]) null} is equivalent to the empty array.
-     *
-     * <p>This method first searches the class C represented by this {@code Class},
-     * then the superclasses of C,
-     * and finally the interfaces implemented by C and its superclasses.
-     *
-     * <p>Use {@link #getDeclaredMethod} if you don't want to search superclasses.
-     *
-     * @throws NoSuchMethodException
-     *             if the method can not be found.
-     */
-    public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException {
-        Member member = getConstructorOrMethod(name, true, true, parameterTypes);
-        if (member instanceof Constructor) {
-            throw new NoSuchMethodException(name);
-        }
-        return (Method) member;
-    }
-
-    /**
-     * Returns an array containing {@code Method} objects for all public methods
-     * for the class C represented by this {@code Class}. Methods may be
-     * declared in C, the interfaces it implements or in the superclasses of C.
-     * The elements in the returned array are in no particular order.
-     *
-     * <p>If there are no public methods or if this {@code Class} represents a
-     * primitive type or {@code void} then an empty array is returned.
-     *
-     * @see #getDeclaredMethods()
-     */
-    public Method[] getMethods() {
-        List<Method> methods = new ArrayList<Method>();
-        getPublicMethodsRecursive(methods);
-
-        /*
-         * Remove methods defined by multiple types, preferring to keep methods
-         * declared by derived types.
-         */
-        CollectionUtils.removeDuplicates(methods, Method.ORDER_BY_SIGNATURE);
-        return methods.toArray(new Method[methods.size()]);
-    }
-
-    /**
-     * Populates {@code result} with public methods defined by this class, its
-     * superclasses, and all implemented interfaces, including overridden methods.
-     */
-    private void getPublicMethodsRecursive(List<Method> result) {
-        // search superclasses
-        for (Class<?> c = this; c != null; c = c.getSuperclass()) {
-            for (Method method : Class.getDeclaredMethods(c, true)) {
-                result.add(method);
-            }
-        }
-
-        // search implemented interfaces
-        for (Class<?> c = this; c != null; c = c.getSuperclass()) {
-            for (Class<?> ifc : c.getInterfaces()) {
-                ifc.getPublicMethodsRecursive(result);
-            }
-        }
-    }
-
-    /**
-     * Returns an integer that represents the modifiers of the class represented
-     * by this {@code Class}. The returned value is a combination of bits
-     * defined by constants in the {@link Modifier} class.
-     */
-    public int getModifiers() {
-        return getModifiers(this, false);
-    }
-
-    /*
-     * Returns the modifiers for the given class.
-     *
-     * {@code ignoreInnerClassesAttrib} determines whether we look for and use the
-     *     flags from an "inner class" attribute
-     */
-    private static native int getModifiers(Class<?> clazz, boolean ignoreInnerClassesAttrib);
-
-    /**
-     * Returns the name of the class represented by this {@code Class}. For a
-     * description of the format which is used, see the class definition of
-     * {@link Class}.
-     */
-    public String getName() {
-        String result = name;
-        return (result == null) ? (name = getNameNative()) : result;
-    }
-
-    private native String getNameNative();
-
-    /**
-     * Returns the simple name of the class represented by this {@code Class} as
-     * defined in the source code. If there is no name (that is, the class is
-     * anonymous) then an empty string is returned. If the receiver is an array
-     * then the name of the underlying type with square braces appended (for
-     * example {@code "Integer[]"}) is returned.
-     *
-     * @return the simple name of the class represented by this {@code Class}.
-     */
-    public String getSimpleName() {
-        if (isArray()) {
-            return getComponentType().getSimpleName() + "[]";
-        }
-
-        String name = getName();
-
-        if (isAnonymousClass()) {
-            return "";
-        }
-
-        if (isMemberClass() || isLocalClass()) {
-            return getInnerClassName();
-        }
-
-        int dot = name.lastIndexOf('.');
-        if (dot != -1) {
-            return name.substring(dot + 1);
-        }
-
-        return name;
-    }
-
-    /*
-     * Returns the simple name of a member or local class, or null otherwise.
-     */
-    private native String getInnerClassName();
-
-    /**
-     * Returns null.
-     */
-    public ProtectionDomain getProtectionDomain() {
-        return null;
-    }
-
-    /**
-     * Returns the URL of the given resource, or 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
-     */
-    public URL getResource(String resourceName) {
-        // Get absolute resource name, but without the leading slash
-        if (resourceName.startsWith("/")) {
-            resourceName = resourceName.substring(1);
-        } else {
-            String pkg = getName();
-            int dot = pkg.lastIndexOf('.');
-            if (dot != -1) {
-                pkg = pkg.substring(0, dot).replace('.', '/');
-            } else {
-                pkg = "";
-            }
-
-            resourceName = pkg + "/" + resourceName;
-        }
-
-        // Delegate to proper class loader
-        ClassLoader loader = getClassLoader();
-        if (loader != null) {
-            return loader.getResource(resourceName);
-        } else {
-            return ClassLoader.getSystemResource(resourceName);
-        }
-    }
-
-    /**
-     * Returns a read-only stream for the contents of the given resource, or 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
-     */
-    public InputStream getResourceAsStream(String resourceName) {
-        // Get absolute resource name, but without the leading slash
-        if (resourceName.startsWith("/")) {
-            resourceName = resourceName.substring(1);
-        } else {
-            String pkg = getName();
-            int dot = pkg.lastIndexOf('.');
-            if (dot != -1) {
-                pkg = pkg.substring(0, dot).replace('.', '/');
-            } else {
-                pkg = "";
-            }
-
-            resourceName = pkg + "/" + resourceName;
-        }
-
-        // Delegate to proper class loader
-        ClassLoader loader = getClassLoader();
-        if (loader != null) {
-            return loader.getResourceAsStream(resourceName);
-        } else {
-            return ClassLoader.getSystemResourceAsStream(resourceName);
-        }
-    }
-
-    /**
-     * 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
-     * files may have different signers. This does not fit well with the original
-     * {@code ClassLoader}-based model of {@code getSigners}.)
-     */
-    public Object[] getSigners() {
-        // See http://code.google.com/p/android/issues/detail?id=1766.
-        return null;
-    }
-
-    /**
-     * Returns the {@code Class} object which represents the superclass of the
-     * class represented by this {@code Class}. If this {@code Class} represents
-     * the {@code Object} class, a primitive type, an interface or void then the
-     * method returns {@code null}. If this {@code Class} represents an array
-     * class then the {@code Object} class is returned.
-     */
-    public native Class<? super T> getSuperclass();
-
-    /**
-     * Returns an array containing {@code TypeVariable} objects for type
-     * variables declared by the generic class represented by this {@code
-     * Class}. Returns an empty array if the class is not generic.
-     */
-    @SuppressWarnings("unchecked")
-    public synchronized TypeVariable<Class<T>>[] getTypeParameters() {
-        String annotationSignature = AnnotationAccess.getSignature(this);
-        if (annotationSignature == null) {
-            return EmptyArray.TYPE_VARIABLE;
-        }
-        GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
-        parser.parseForClass(this, annotationSignature);
-        return parser.formalTypeParameters;
-    }
-
-    /**
-     * Tests whether this {@code Class} represents an annotation class.
-     */
-    public boolean isAnnotation() {
-        final int ACC_ANNOTATION = 0x2000;  // not public in reflect.Modifiers
-        int mod = getModifiers(this, true);
-        return (mod & ACC_ANNOTATION) != 0;
-    }
-
-    @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-
-        if (isDeclaredAnnotationPresent(annotationType)) {
-            return true;
-        }
-
-        if (annotationType.isDeclaredAnnotationPresent(Inherited.class)) {
-            for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
-                if (sup.isDeclaredAnnotationPresent(annotationType)) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Tests whether the class represented by this {@code Class} is
-     * anonymous.
-     */
-    native public boolean isAnonymousClass();
-
-    /**
-     * Tests whether the class represented by this {@code Class} is an array class.
-     */
-    public boolean isArray() {
-        return getComponentType() != null;
-    }
-
-    /**
-     * Tests whether the given class type can be converted to the class
-     * represented by this {@code Class}. Conversion may be done via an identity
-     * conversion or a widening reference conversion (if either the receiver or
-     * the argument represent primitive types, only the identity conversion
-     * applies).
-     *
-     * @throws NullPointerException
-     *             if {@code c} is {@code null}.
-     */
-    public native boolean isAssignableFrom(Class<?> c);
-
-    /**
-     * Tests whether the class represented by this {@code Class} is an
-     * {@code enum}.
-     */
-    public boolean isEnum() {
-        if (getSuperclass() != Enum.class) {
-            return false;
-        }
-        int mod = getModifiers(this, true);
-        return (mod & 0x4000) != 0;
-    }
-
-    /**
-     * Tests whether the given object can be cast to the class
-     * represented by this {@code Class}. This is the runtime version of the
-     * {@code instanceof} operator.
-     *
-     * @return {@code true} if {@code object} can be cast to the type
-     *         represented by this {@code Class}; {@code false} if {@code
-     *         object} is {@code null} or cannot be cast.
-     */
-    public native boolean isInstance(Object object);
-
-    /**
-     * Tests whether this {@code Class} represents an interface.
-     */
-    public native boolean isInterface();
-
-    /**
-     * Tests whether the class represented by this {@code Class} is defined
-     * locally.
-     */
-    public boolean isLocalClass() {
-        boolean enclosed = (getEnclosingMethod() != null ||
-                         getEnclosingConstructor() != null);
-        return enclosed && !isAnonymousClass();
-    }
-
-    /**
-     * Tests whether the class represented by this {@code Class} is a member
-     * class.
-     */
-    public boolean isMemberClass() {
-        return getDeclaringClass() != null;
-    }
-
-    /**
-     * Tests whether this {@code Class} represents a primitive type.
-     */
-    public native boolean isPrimitive();
-
-    /**
-     * Tests whether this {@code Class} represents a synthetic type.
-     */
-    public boolean isSynthetic() {
-        final int ACC_SYNTHETIC = 0x1000;   // not public in reflect.Modifiers
-        int mod = getModifiers(this, true);
-        return (mod & ACC_SYNTHETIC) != 0;
-    }
-
-    /**
-     * Returns a new instance of the class represented by this {@code Class},
-     * created by invoking the default (that is, zero-argument) constructor. If
-     * there is no such constructor, or if the creation fails (either because of
-     * a lack of available memory or because an exception is thrown by the
-     * constructor), an {@code InstantiationException} is thrown. If the default
-     * constructor exists but is not accessible from the context where this
-     * method is invoked, an {@code IllegalAccessException} is thrown.
-     *
-     * @throws IllegalAccessException
-     *             if the default constructor is not visible.
-     * @throws InstantiationException
-     *             if the instance can not be created.
-     */
-    public T newInstance() throws InstantiationException, IllegalAccessException {
-        return newInstanceImpl();
-    }
-
-    private native T newInstanceImpl() throws IllegalAccessException, InstantiationException;
-
-    @Override
-    public String toString() {
-        if (isPrimitive()) {
-            return getSimpleName();
-        }
-        return (isInterface() ? "interface " : "class ") + getName();
-    }
-
-    /**
-     * Returns the {@code Package} of which the class represented by this
-     * {@code Class} is a member. Returns {@code null} if no {@code Package}
-     * 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.
-        ClassLoader loader = getClassLoader();
-        if (loader != null) {
-            String name = getName();
-            int dot = name.lastIndexOf('.');
-            return (dot != -1 ? loader.getPackage(name.substring(0, dot)) : null);
-        }
-        return null;
-    }
-
-    /**
-     * Returns the assertion status for the class represented by this {@code
-     * Class}. Assertion is enabled / disabled based on the class loader,
-     * package or class default at runtime.
-     */
-    public native boolean desiredAssertionStatus();
-
-    /**
-     * Casts this {@code Class} to represent a subclass of the given class.
-     * If successful, this {@code Class} is returned; otherwise a {@code
-     * ClassCastException} is thrown.
-     *
-     * @throws ClassCastException
-     *             if this {@code Class} cannot be cast to the given type.
-     */
-    @SuppressWarnings("unchecked")
-    public <U> Class<? extends U> asSubclass(Class<U> c) {
-        if (c.isAssignableFrom(this)) {
-            return (Class<? extends U>)this;
-        }
-        String actualClassName = this.getName();
-        String desiredClassName = c.getName();
-        throw new ClassCastException(actualClassName + " cannot be cast to " + desiredClassName);
-    }
-
-    /**
-     * Casts the given object to the type represented by this {@code Class}.
-     * If the object is {@code null} then the result is also {@code null}.
-     *
-     * @throws ClassCastException
-     *             if the object cannot be cast to the given type.
-     */
-    @SuppressWarnings("unchecked")
-    public T cast(Object obj) {
-        if (obj == null) {
-            return null;
-        } else if (this.isInstance(obj)) {
-            return (T)obj;
-        }
-        String actualClassName = obj.getClass().getName();
-        String desiredClassName = this.getName();
-        throw new ClassCastException(actualClassName + " cannot be cast to " + desiredClassName);
-    }
-
-    /**
-     * Copies two arrays into one. Assumes that the destination array is large
-     * enough.
-     *
-     * @param result the destination array
-     * @param head the first source array
-     * @param tail the second source array
-     * @return the destination array, that is, result
-     */
-    private static <T extends Object> T[] arraycopy(T[] result, T[] head, T[] tail) {
-        System.arraycopy(head, 0, result, 0, head.length);
-        System.arraycopy(tail, 0, result, head.length, tail.length);
-        return result;
-    }
-
-    /**
-     * The annotation directory offset of this class in its own Dex, or 0 if it
-     * is unknown.
-     *
-     * TODO: 0 is a sentinel that means 'no annotations directory'; this should be -1 if unknown
-     *
-     * @hide
-     */
-    public int getDexAnnotationDirectoryOffset() {
-        Dex dex = getDex();
-        if (dex == null) {
-            return 0;
-        }
-        int classDefIndex = getDexClassDefIndex();
-        if (classDefIndex < 0) {
-            return 0;
-        }
-        return dex.annotationDirectoryOffsetFromClassDefIndex(classDefIndex);
-    }
-
-
-    /**
-     * Returns a resolved type from the dex cache, computing the type from the dex file if
-     * necessary.
-     * TODO: use Dalvik's dex cache.
-     * @hide
-     */
-    public Class<?> getDexCacheType(Dex dex, int typeIndex) {
-        String internalName = dex.typeNames().get(typeIndex);
-        return InternalNames.getClass(getClassLoader(), internalName);
-    }
-
-    /**
-     * Returns a string from the dex cache, computing the string from the dex file if necessary.
-     *
-     * @hide
-     */
-    public String getDexCacheString(Dex dex, int dexStringIndex) {
-        return dex.strings().get(dexStringIndex);
-    }
-
-
-    private static class Caches {
-        /**
-         * Cache to avoid frequent recalculation of generic interfaces, which is generally uncommon.
-         * Sized sufficient to allow ConcurrentHashMapTest to run without recalculating its generic
-         * interfaces (required to avoid time outs). Validated by running reflection heavy code
-         * such as applications using Guice-like frameworks.
-         */
-        private static final BasicLruCache<Class, Type[]> genericInterfaces
-            = new BasicLruCache<Class, Type[]>(8);
-    }
-}
diff --git a/libdvm/src/main/java/java/lang/ClassLoader.java b/libdvm/src/main/java/java/lang/ClassLoader.java
deleted file mode 100644
index c6a80913..0000000
--- a/libdvm/src/main/java/java/lang/ClassLoader.java
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import dalvik.system.PathClassLoader;
-import dalvik.system.VMStack;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.nio.ByteBuffer;
-import java.security.ProtectionDomain;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Loads classes and resources from a repository. One or more class loaders are
- * installed at runtime. These are consulted whenever the runtime system needs a
- * specific class that is not yet available in-memory. Typically, class loaders
- * are grouped into a tree where child class loaders delegate all requests to
- * parent class loaders. Only if the parent class loader cannot satisfy the
- * request, the child class loader itself tries to handle it.
- * <p>
- * {@code ClassLoader} is an abstract class that implements the common
- * infrastructure required by all class loaders. Android provides several
- * concrete implementations of the class, with
- * {@link dalvik.system.PathClassLoader} being the one typically used. Other
- * applications may implement subclasses of {@code ClassLoader} to provide
- * special ways for loading classes.
- * </p>
- * @see Class
- */
-public abstract class ClassLoader {
-
-    /**
-     * The 'System' ClassLoader - the one that is responsible for loading
-     * classes from the classpath. It is not equal to the bootstrap class loader -
-     * that one handles the built-in classes.
-     *
-     * Because of a potential class initialization race between ClassLoader and
-     * java.lang.System, reproducible when using JDWP with "suspend=y", we defer
-     * creation of the system class loader until first use. We use a static
-     * inner class to get synchronization at init time without having to sync on
-     * every access.
-     *
-     * @see #getSystemClassLoader()
-     */
-    static private class SystemClassLoader {
-        public static ClassLoader loader = ClassLoader.createSystemClassLoader();
-    }
-
-    /**
-     * The parent ClassLoader.
-     */
-    private ClassLoader parent;
-
-    /**
-     * The packages known to the class loader.
-     */
-    private Map<String, Package> packages = new HashMap<String, Package>();
-
-    /**
-     * Create the system class loader. Note this is NOT the bootstrap class
-     * loader (which is managed by the VM). We use a null value for the parent
-     * to indicate that the bootstrap loader is our parent.
-     */
-    private static ClassLoader createSystemClassLoader() {
-        String classPath = System.getProperty("java.class.path", ".");
-
-        // String[] paths = classPath.split(":");
-        // URL[] urls = new URL[paths.length];
-        // for (int i = 0; i < paths.length; i++) {
-        // try {
-        // urls[i] = new URL("file://" + paths[i]);
-        // }
-        // catch (Exception ex) {
-        // ex.printStackTrace();
-        // }
-        // }
-        //
-        // return new java.net.URLClassLoader(urls, null);
-
-        // TODO Make this a java.net.URLClassLoader once we have those?
-        return new PathClassLoader(classPath, BootClassLoader.getInstance());
-    }
-
-    /**
-     * Returns the system class loader. This is the parent for new
-     * {@code ClassLoader} instances and is typically the class loader used to
-     * start the application.
-     */
-    public static ClassLoader getSystemClassLoader() {
-        return SystemClassLoader.loader;
-    }
-
-    /**
-     * Finds the URL of the resource with the specified name. The system class
-     * loader's resource lookup algorithm is used to find the resource.
-     *
-     * @return the {@code URL} object for the requested resource or {@code null}
-     *         if the resource can not be found.
-     * @param resName
-     *            the name of the resource to find.
-     * @see Class#getResource
-     */
-    public static URL getSystemResource(String resName) {
-        return SystemClassLoader.loader.getResource(resName);
-    }
-
-    /**
-     * Returns an enumeration of URLs for the resource with the specified name.
-     * The system class loader's resource lookup algorithm is used to find the
-     * resource.
-     *
-     * @return an enumeration of {@code URL} objects containing the requested
-     *         resources.
-     * @param resName
-     *            the name of the resource to find.
-     * @throws IOException
-     *             if an I/O error occurs.
-     */
-    public static Enumeration<URL> getSystemResources(String resName) throws IOException {
-        return SystemClassLoader.loader.getResources(resName);
-    }
-
-    /**
-     * Returns a stream for the resource with the specified name. The system
-     * class loader's resource lookup algorithm is used to find the resource.
-     * Basically, the contents of the java.class.path are searched in order,
-     * looking for a path which matches the specified resource.
-     *
-     * @return a stream for the resource or {@code null}.
-     * @param resName
-     *            the name of the resource to find.
-     * @see Class#getResourceAsStream
-     */
-    public static InputStream getSystemResourceAsStream(String resName) {
-        return SystemClassLoader.loader.getResourceAsStream(resName);
-    }
-
-    /**
-     * Constructs a new instance of this class with the system class loader as
-     * its parent.
-     */
-    protected ClassLoader() {
-        this(getSystemClassLoader(), false);
-    }
-
-    /**
-     * Constructs a new instance of this class with the specified class loader
-     * as its parent.
-     *
-     * @param parentLoader
-     *            The {@code ClassLoader} to use as the new class loader's
-     *            parent.
-     */
-    protected ClassLoader(ClassLoader parentLoader) {
-        this(parentLoader, false);
-    }
-
-    /*
-     * constructor for the BootClassLoader which needs parent to be null.
-     */
-    ClassLoader(ClassLoader parentLoader, boolean nullAllowed) {
-        if (parentLoader == null && !nullAllowed) {
-            throw new NullPointerException("parentLoader == null && !nullAllowed");
-        }
-        parent = parentLoader;
-    }
-
-    /**
-     * Constructs a new class from an array of bytes containing a class
-     * definition in class file format.
-     *
-     * @param classRep
-     *            the memory image of a class file.
-     * @param offset
-     *            the offset into {@code classRep}.
-     * @param length
-     *            the length of the class file.
-     * @return the {@code Class} object created from the specified subset of
-     *         data in {@code classRep}.
-     * @throws ClassFormatError
-     *             if {@code classRep} does not contain a valid class.
-     * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0}, {@code length < 0} or if
-     *             {@code offset + length} is greater than the length of
-     *             {@code classRep}.
-     * @deprecated Use {@link #defineClass(String, byte[], int, int)} instead.
-     */
-    @Deprecated
-    protected final Class<?> defineClass(byte[] classRep, int offset, int length)
-            throws ClassFormatError {
-        throw new UnsupportedOperationException("can't load this type of class file");
-    }
-
-    /**
-     * Constructs a new class from an array of bytes containing a class
-     * definition in class file format.
-     *
-     * @param className
-     *            the expected name of the new class, may be {@code null} if not
-     *            known.
-     * @param classRep
-     *            the memory image of a class file.
-     * @param offset
-     *            the offset into {@code classRep}.
-     * @param length
-     *            the length of the class file.
-     * @return the {@code Class} object created from the specified subset of
-     *         data in {@code classRep}.
-     * @throws ClassFormatError
-     *             if {@code classRep} does not contain a valid class.
-     * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0}, {@code length < 0} or if
-     *             {@code offset + length} is greater than the length of
-     *             {@code classRep}.
-     */
-    protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length)
-            throws ClassFormatError {
-        throw new UnsupportedOperationException("can't load this type of class file");
-    }
-
-    /**
-     * Constructs a new class from an array of bytes containing a class
-     * definition in class file format and assigns the specified protection
-     * domain to the new class. If the provided protection domain is
-     * {@code null} then a default protection domain is assigned to the class.
-     *
-     * @param className
-     *            the expected name of the new class, may be {@code null} if not
-     *            known.
-     * @param classRep
-     *            the memory image of a class file.
-     * @param offset
-     *            the offset into {@code classRep}.
-     * @param length
-     *            the length of the class file.
-     * @param protectionDomain
-     *            the protection domain to assign to the loaded class, may be
-     *            {@code null}.
-     * @return the {@code Class} object created from the specified subset of
-     *         data in {@code classRep}.
-     * @throws ClassFormatError
-     *             if {@code classRep} does not contain a valid class.
-     * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0}, {@code length < 0} or if
-     *             {@code offset + length} is greater than the length of
-     *             {@code classRep}.
-     * @throws NoClassDefFoundError
-     *             if {@code className} is not equal to the name of the class
-     *             contained in {@code classRep}.
-     */
-    protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length,
-            ProtectionDomain protectionDomain) throws java.lang.ClassFormatError {
-        throw new UnsupportedOperationException("can't load this type of class file");
-    }
-
-    /**
-     * Defines a new class with the specified name, byte code from the byte
-     * buffer and the optional protection domain. If the provided protection
-     * domain is {@code null} then a default protection domain is assigned to
-     * the class.
-     *
-     * @param name
-     *            the expected name of the new class, may be {@code null} if not
-     *            known.
-     * @param b
-     *            the byte buffer containing the byte code of the new class.
-     * @param protectionDomain
-     *            the protection domain to assign to the loaded class, may be
-     *            {@code null}.
-     * @return the {@code Class} object created from the data in {@code b}.
-     * @throws ClassFormatError
-     *             if {@code b} does not contain a valid class.
-     * @throws NoClassDefFoundError
-     *             if {@code className} is not equal to the name of the class
-     *             contained in {@code b}.
-     */
-    protected final Class<?> defineClass(String name, ByteBuffer b,
-            ProtectionDomain protectionDomain) throws ClassFormatError {
-
-        byte[] temp = new byte[b.remaining()];
-        b.get(temp);
-        return defineClass(name, temp, 0, temp.length, protectionDomain);
-    }
-
-    /**
-     * Overridden by subclasses, throws a {@code ClassNotFoundException} by
-     * default. This method is called by {@code loadClass} after the parent
-     * {@code ClassLoader} has failed to find a loaded class of the same name.
-     *
-     * @param className
-     *            the name of the class to look for.
-     * @return the {@code Class} object that is found.
-     * @throws ClassNotFoundException
-     *             if the class cannot be found.
-     */
-    protected Class<?> findClass(String className) throws ClassNotFoundException {
-        throw new ClassNotFoundException(className);
-    }
-
-    /**
-     * Returns the class with the specified name if it has already been loaded
-     * by the VM or {@code null} if it has not yet been loaded.
-     *
-     * @param className
-     *            the name of the class to look for.
-     * @return the {@code Class} object or {@code null} if the requested class
-     *         has not been loaded.
-     */
-    protected final Class<?> findLoadedClass(String className) {
-        ClassLoader loader;
-        if (this == BootClassLoader.getInstance())
-            loader = null;
-        else
-            loader = this;
-        return VMClassLoader.findLoadedClass(loader, className);
-    }
-
-    /**
-     * Finds the class with the specified name, loading it using the system
-     * class loader if necessary.
-     *
-     * @param className
-     *            the name of the class to look for.
-     * @return the {@code Class} object with the requested {@code className}.
-     * @throws ClassNotFoundException
-     *             if the class can not be found.
-     */
-    protected final Class<?> findSystemClass(String className) throws ClassNotFoundException {
-        return Class.forName(className, false, getSystemClassLoader());
-    }
-
-    /**
-     * Returns this class loader's parent.
-     *
-     * @return this class loader's parent or {@code null}.
-     */
-    public final ClassLoader getParent() {
-        return parent;
-    }
-
-    /**
-     * Returns the URL of the resource with the specified name. This
-     * implementation first tries to use the parent class loader to find the
-     * resource; if this fails then {@link #findResource(String)} is called to
-     * find the requested resource.
-     *
-     * @param resName
-     *            the name of the resource to find.
-     * @return the {@code URL} object for the requested resource or {@code null}
-     *         if the resource can not be found
-     * @see Class#getResource
-     */
-    public URL getResource(String resName) {
-        URL resource = parent.getResource(resName);
-        if (resource == null) {
-            resource = findResource(resName);
-        }
-        return resource;
-    }
-
-    /**
-     * Returns an enumeration of URLs for the resource with the specified name.
-     * This implementation first uses this class loader's parent to find the
-     * resource, then it calls {@link #findResources(String)} to get additional
-     * URLs. The returned enumeration contains the {@code URL} objects of both
-     * find operations.
-     *
-     * @return an enumeration of {@code URL} objects for the requested resource.
-     * @param resName
-     *            the name of the resource to find.
-     * @throws IOException
-     *             if an I/O error occurs.
-     */
-    @SuppressWarnings("unchecked")
-    public Enumeration<URL> getResources(String resName) throws IOException {
-
-        Enumeration first = parent.getResources(resName);
-        Enumeration second = findResources(resName);
-
-        return new TwoEnumerationsInOne(first, second);
-    }
-
-    /**
-     * Returns a stream for the resource with the specified name. See
-     * {@link #getResource(String)} for a description of the lookup algorithm
-     * used to find the resource.
-     *
-     * @return a stream for the resource or {@code null} if the resource can not be found
-     * @param resName
-     *            the name of the resource to find.
-     * @see Class#getResourceAsStream
-     */
-    public InputStream getResourceAsStream(String resName) {
-        try {
-            URL url = getResource(resName);
-            if (url != null) {
-                return url.openStream();
-            }
-        } catch (IOException ex) {
-            // Don't want to see the exception.
-        }
-
-        return null;
-    }
-
-    /**
-     * Loads the class with the specified name. Invoking this method is
-     * equivalent to calling {@code loadClass(className, false)}.
-     * <p>
-     * <strong>Note:</strong> In the Android reference implementation, the
-     * second parameter of {@link #loadClass(String, boolean)} is ignored
-     * anyway.
-     * </p>
-     *
-     * @return the {@code Class} object.
-     * @param className
-     *            the name of the class to look for.
-     * @throws ClassNotFoundException
-     *             if the class can not be found.
-     */
-    public Class<?> loadClass(String className) throws ClassNotFoundException {
-        return loadClass(className, false);
-    }
-
-    /**
-     * Loads the class with the specified name, optionally linking it after
-     * loading. The following steps are performed:
-     * <ol>
-     * <li> Call {@link #findLoadedClass(String)} to determine if the requested
-     * class has already been loaded.</li>
-     * <li>If the class has not yet been loaded: Invoke this method on the
-     * parent class loader.</li>
-     * <li>If the class has still not been loaded: Call
-     * {@link #findClass(String)} to find the class.</li>
-     * </ol>
-     * <p>
-     * <strong>Note:</strong> In the Android reference implementation, the
-     * {@code resolve} parameter is ignored; classes are never linked.
-     * </p>
-     *
-     * @return the {@code Class} object.
-     * @param className
-     *            the name of the class to look for.
-     * @param resolve
-     *            Indicates if the class should be resolved after loading. This
-     *            parameter is ignored on the Android reference implementation;
-     *            classes are not resolved.
-     * @throws ClassNotFoundException
-     *             if the class can not be found.
-     */
-    protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
-        Class<?> clazz = findLoadedClass(className);
-
-        if (clazz == null) {
-            try {
-                clazz = parent.loadClass(className, false);
-            } catch (ClassNotFoundException e) {
-                // Don't want to see this.
-            }
-
-            if (clazz == null) {
-                clazz = findClass(className);
-            }
-        }
-
-        return clazz;
-    }
-
-    /**
-     * Forces a class to be linked (initialized). If the class has already been
-     * linked this operation has no effect.
-     * <p>
-     * <strong>Note:</strong> In the Android reference implementation, this
-     * method has no effect.
-     * </p>
-     *
-     * @param clazz
-     *            the class to link.
-     */
-    protected final void resolveClass(Class<?> clazz) {
-        // no-op, doesn't make sense on android.
-    }
-
-    /**
-     * Finds the URL of the resource with the specified name. This
-     * implementation just returns {@code null}; it should be overridden in
-     * subclasses.
-     *
-     * @param resName
-     *            the name of the resource to find.
-     * @return the {@code URL} object for the requested resource.
-     */
-    protected URL findResource(String resName) {
-        return null;
-    }
-
-    /**
-     * Finds an enumeration of URLs for the resource with the specified name.
-     * This implementation just returns an empty {@code Enumeration}; it should
-     * be overridden in subclasses.
-     *
-     * @param resName
-     *            the name of the resource to find.
-     * @return an enumeration of {@code URL} objects for the requested resource.
-     * @throws IOException
-     *             if an I/O error occurs.
-     */
-    @SuppressWarnings( {
-            "unchecked", "unused"
-    })
-    protected Enumeration<URL> findResources(String resName) throws IOException {
-        return Collections.emptyEnumeration();
-    }
-
-    /**
-     * Returns the absolute path of the native library with the specified name,
-     * or {@code null}. If this method returns {@code null} then the virtual
-     * machine searches the directories specified by the system property
-     * "java.library.path".
-     * <p>
-     * This implementation always returns {@code null}.
-     * </p>
-     *
-     * @param libName
-     *            the name of the library to find.
-     * @return the absolute path of the library.
-     */
-    protected String findLibrary(String libName) {
-        return null;
-    }
-
-    /**
-     * Returns the package with the specified name. Package information is
-     * searched in this class loader.
-     *
-     * @param name
-     *            the name of the package to find.
-     * @return the package with the requested name; {@code null} if the package
-     *         can not be found.
-     */
-    protected Package getPackage(String name) {
-        synchronized (packages) {
-            return packages.get(name);
-        }
-    }
-
-    /**
-     * Returns all the packages known to this class loader.
-     *
-     * @return an array with all packages known to this class loader.
-     */
-    protected Package[] getPackages() {
-        synchronized (packages) {
-            Collection<Package> col = packages.values();
-            Package[] result = new Package[col.size()];
-            col.toArray(result);
-            return result;
-        }
-    }
-
-    /**
-     * Defines and returns a new {@code Package} using the specified
-     * information. If {@code sealBase} is {@code null}, the package is left
-     * unsealed. Otherwise, the package is sealed using this URL.
-     *
-     * @param name
-     *            the name of the package.
-     * @param specTitle
-     *            the title of the specification.
-     * @param specVersion
-     *            the version of the specification.
-     * @param specVendor
-     *            the vendor of the specification.
-     * @param implTitle
-     *            the implementation title.
-     * @param implVersion
-     *            the implementation version.
-     * @param implVendor
-     *            the specification vendor.
-     * @param sealBase
-     *            the URL used to seal this package or {@code null} to leave the
-     *            package unsealed.
-     * @return the {@code Package} object that has been created.
-     * @throws IllegalArgumentException
-     *             if a package with the specified name already exists.
-     */
-    protected Package definePackage(String name, String specTitle, String specVersion,
-            String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)
-            throws IllegalArgumentException {
-
-        synchronized (packages) {
-            if (packages.containsKey(name)) {
-                throw new IllegalArgumentException("Package " + name + " already defined");
-            }
-
-            Package newPackage = new Package(name, specTitle, specVersion, specVendor, implTitle,
-                    implVersion, implVendor, sealBase);
-
-            packages.put(name, newPackage);
-
-            return newPackage;
-        }
-    }
-
-    /**
-     * Sets the signers of the specified class. This implementation does
-     * nothing.
-     *
-     * @param c
-     *            the {@code Class} object for which to set the signers.
-     * @param signers
-     *            the signers for {@code c}.
-     */
-    protected final void setSigners(Class<?> c, Object[] signers) {
-    }
-
-    /**
-     * Sets the assertion status of the class with the specified name.
-     * <p>
-     * <strong>Note: </strong>This method does nothing in the Android reference
-     * implementation.
-     * </p>
-     *
-     * @param cname
-     *            the name of the class for which to set the assertion status.
-     * @param enable
-     *            the new assertion status.
-     */
-    public void setClassAssertionStatus(String cname, boolean enable) {
-    }
-
-    /**
-     * Sets the assertion status of the package with the specified name.
-     * <p>
-     * <strong>Note: </strong>This method does nothing in the Android reference
-     * implementation.
-     * </p>
-     *
-     * @param pname
-     *            the name of the package for which to set the assertion status.
-     * @param enable
-     *            the new assertion status.
-     */
-    public void setPackageAssertionStatus(String pname, boolean enable) {
-    }
-
-    /**
-     * Sets the default assertion status for this class loader.
-     * <p>
-     * <strong>Note: </strong>This method does nothing in the Android reference
-     * implementation.
-     * </p>
-     *
-     * @param enable
-     *            the new assertion status.
-     */
-    public void setDefaultAssertionStatus(boolean enable) {
-    }
-
-    /**
-     * Sets the default assertion status for this class loader to {@code false}
-     * and removes any package default and class assertion status settings.
-     * <p>
-     * <strong>Note:</strong> This method does nothing in the Android reference
-     * implementation.
-     * </p>
-     */
-    public void clearAssertionStatus() {
-    }
-}
-
-/*
- * Provides a helper class that combines two existing URL enumerations into one.
- * It is required for the getResources() methods. Items are fetched from the
- * first enumeration until it's empty, then from the second one.
- */
-class TwoEnumerationsInOne implements Enumeration<URL> {
-
-    private Enumeration<URL> first;
-
-    private Enumeration<URL> second;
-
-    public TwoEnumerationsInOne(Enumeration<URL> first, Enumeration<URL> second) {
-        this.first = first;
-        this.second = second;
-    }
-
-    public boolean hasMoreElements() {
-        return first.hasMoreElements() || second.hasMoreElements();
-    }
-
-    public URL nextElement() {
-        if (first.hasMoreElements()) {
-            return first.nextElement();
-        } else {
-            return second.nextElement();
-        }
-    }
-
-}
-
-/**
- * Provides an explicit representation of the boot class loader. It sits at the
- * head of the class loader chain and delegates requests to the VM's internal
- * class loading mechanism.
- */
-class BootClassLoader extends ClassLoader {
-
-    private static BootClassLoader instance;
-
-    @FindBugsSuppressWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED")
-    public static synchronized BootClassLoader getInstance() {
-        if (instance == null) {
-            instance = new BootClassLoader();
-        }
-
-        return instance;
-    }
-
-    public BootClassLoader() {
-        super(null, true);
-    }
-
-    @Override
-    protected Class<?> findClass(String name) throws ClassNotFoundException {
-        return VMClassLoader.loadClass(name, false);
-    }
-
-    @Override
-    protected URL findResource(String name) {
-        return VMClassLoader.getResource(name);
-    }
-
-    @SuppressWarnings("unused")
-    @Override
-    protected Enumeration<URL> findResources(String resName) throws IOException {
-        return Collections.enumeration(VMClassLoader.getResources(resName));
-    }
-
-    /**
-     * Returns package information for the given package. Unfortunately, the
-     * Android BootClassLoader doesn't really have this information, and as a
-     * non-secure ClassLoader, it isn't even required to, according to the spec.
-     * Yet, we want to provide it, in order to make all those hopeful callers of
-     * {@code myClass.getPackage().getName()} happy. Thus we construct a Package
-     * object the first time it is being requested and fill most of the fields
-     * with dummy values. The Package object is then put into the ClassLoader's
-     * Package cache, so we see the same one next time. We don't create Package
-     * objects for null arguments or for the default package.
-     * <p>
-     * There a limited chance that we end up with multiple Package objects
-     * representing the same package: It can happen when when a package is
-     * scattered across different JAR files being loaded by different
-     * ClassLoaders. Rather unlikely, and given that this whole thing is more or
-     * less a workaround, probably not worth the effort.
-     */
-    @Override
-    protected Package getPackage(String name) {
-        if (name != null && !name.isEmpty()) {
-            synchronized (this) {
-                Package pack = super.getPackage(name);
-
-                if (pack == null) {
-                    pack = definePackage(name, "Unknown", "0.0", "Unknown", "Unknown", "0.0",
-                            "Unknown", null);
-                }
-
-                return pack;
-            }
-        }
-
-        return null;
-    }
-
-    @Override
-    public URL getResource(String resName) {
-        return findResource(resName);
-    }
-
-    @Override
-    protected Class<?> loadClass(String className, boolean resolve)
-           throws ClassNotFoundException {
-        Class<?> clazz = findLoadedClass(className);
-
-        if (clazz == null) {
-            clazz = findClass(className);
-        }
-
-        return clazz;
-    }
-
-    @Override
-    public Enumeration<URL> getResources(String resName) throws IOException {
-        return findResources(resName);
-    }
-}
-
-/**
- * TODO Open issues - Missing / empty methods - Signer stuff - Protection
- * domains - Assertions
- */
diff --git a/libdvm/src/main/java/java/lang/Daemons.java b/libdvm/src/main/java/java/lang/Daemons.java
deleted file mode 100644
index 78a4152..0000000
--- a/libdvm/src/main/java/java/lang/Daemons.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import dalvik.system.VMRuntime;
-import java.lang.ref.FinalizerReference;
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.util.concurrent.TimeoutException;
-import libcore.util.EmptyArray;
-
-/**
- * Calls Object.finalize() on objects in the finalizer reference queue. The VM
- * will abort if any finalize() call takes more than the maximum finalize time
- * to complete.
- *
- * @hide
- */
-public final class Daemons {
-    private static final int NANOS_PER_MILLI = 1000 * 1000;
-    private static final int NANOS_PER_SECOND = NANOS_PER_MILLI * 1000;
-    private static final long MAX_FINALIZE_NANOS = 10L * NANOS_PER_SECOND;
-
-    public static void start() {
-        ReferenceQueueDaemon.INSTANCE.start();
-        FinalizerDaemon.INSTANCE.start();
-        FinalizerWatchdogDaemon.INSTANCE.start();
-    }
-
-    public static void stop() {
-        ReferenceQueueDaemon.INSTANCE.stop();
-        FinalizerDaemon.INSTANCE.stop();
-        FinalizerWatchdogDaemon.INSTANCE.stop();
-    }
-
-    /**
-     * A background task that provides runtime support to the application.
-     * Daemons can be stopped and started, but only so that the zygote can be a
-     * single-threaded process when it forks.
-     */
-    private static abstract class Daemon implements Runnable {
-        private Thread thread;
-
-        public synchronized void start() {
-            if (thread != null) {
-                throw new IllegalStateException("already running");
-            }
-            thread = new Thread(ThreadGroup.mSystem, this,
-                getClass().getSimpleName());
-            thread.setDaemon(true);
-            thread.start();
-        }
-
-        public abstract void run();
-
-        /**
-         * Returns true while the current thread should continue to run; false
-         * when it should return.
-         */
-        protected synchronized boolean isRunning() {
-            return thread != null;
-        }
-
-        public synchronized void interrupt() {
-            if (thread == null) {
-                throw new IllegalStateException("not running");
-            }
-            thread.interrupt();
-        }
-
-        /**
-         * Waits for the runtime thread to stop. This interrupts the thread
-         * currently running the runnable and then waits for it to exit.
-         */
-        public void stop() {
-            Thread threadToStop;
-            synchronized (this) {
-                threadToStop = thread;
-                thread = null;
-            }
-            if (threadToStop == null) {
-                throw new IllegalStateException("not running");
-            }
-            threadToStop.interrupt();
-            while (true) {
-                try {
-                    threadToStop.join();
-                    return;
-                } catch (InterruptedException ignored) {
-                }
-            }
-        }
-
-        /**
-         * Returns the current stack trace of the thread, or an empty stack trace
-         * if the thread is not currently running.
-         */
-        public synchronized StackTraceElement[] getStackTrace() {
-            return thread != null ? thread.getStackTrace() : EmptyArray.STACK_TRACE_ELEMENT;
-        }
-    }
-
-    /**
-     * This heap management thread moves elements from the garbage collector's
-     * pending list to the managed reference queue.
-     */
-    private static class ReferenceQueueDaemon extends Daemon {
-        private static final ReferenceQueueDaemon INSTANCE = new ReferenceQueueDaemon();
-
-        @Override public void run() {
-            while (isRunning()) {
-                Reference<?> list;
-                try {
-                    synchronized (ReferenceQueue.class) {
-                        while (ReferenceQueue.unenqueued == null) {
-                            ReferenceQueue.class.wait();
-                        }
-                        list = ReferenceQueue.unenqueued;
-                        ReferenceQueue.unenqueued = null;
-                    }
-                } catch (InterruptedException e) {
-                    continue;
-                }
-                enqueue(list);
-            }
-        }
-
-        private void enqueue(Reference<?> list) {
-            while (list != null) {
-                Reference<?> reference;
-                // pendingNext is owned by the GC so no synchronization is required
-                if (list == list.pendingNext) {
-                    reference = list;
-                    reference.pendingNext = null;
-                    list = null;
-                } else {
-                    reference = list.pendingNext;
-                    list.pendingNext = reference.pendingNext;
-                    reference.pendingNext = null;
-                }
-                reference.enqueueInternal();
-            }
-        }
-    }
-
-    private static class FinalizerDaemon extends Daemon {
-        private static final FinalizerDaemon INSTANCE = new FinalizerDaemon();
-        private final ReferenceQueue<Object> queue = FinalizerReference.queue;
-        private volatile Object finalizingObject;
-        private volatile long finalizingStartedNanos;
-
-        @Override public void run() {
-            while (isRunning()) {
-                // Take a reference, blocking until one is ready or the thread should stop
-                try {
-                    doFinalize((FinalizerReference<?>) queue.remove());
-                } catch (InterruptedException ignored) {
-                }
-            }
-        }
-
-        @FindBugsSuppressWarnings("FI_EXPLICIT_INVOCATION")
-        private void doFinalize(FinalizerReference<?> reference) {
-            FinalizerReference.remove(reference);
-            Object object = reference.get();
-            reference.clear();
-            try {
-                finalizingStartedNanos = System.nanoTime();
-                finalizingObject = object;
-                synchronized (FinalizerWatchdogDaemon.INSTANCE) {
-                    FinalizerWatchdogDaemon.INSTANCE.notify();
-                }
-                object.finalize();
-            } catch (Throwable ex) {
-                // The RI silently swallows these, but Android has always logged.
-                System.logE("Uncaught exception thrown by finalizer", ex);
-            } finally {
-                finalizingObject = null;
-            }
-        }
-    }
-
-    /**
-     * The watchdog exits the VM if the finalizer ever gets stuck. We consider
-     * the finalizer to be stuck if it spends more than MAX_FINALIZATION_MILLIS
-     * on one instance.
-     */
-    private static class FinalizerWatchdogDaemon extends Daemon {
-        private static final FinalizerWatchdogDaemon INSTANCE = new FinalizerWatchdogDaemon();
-
-        @Override public void run() {
-            while (isRunning()) {
-                Object object = waitForObject();
-                if (object == null) {
-                    // We have been interrupted, need to see if this daemon has been stopped.
-                    continue;
-                }
-                boolean finalized = waitForFinalization(object);
-                if (!finalized && !VMRuntime.getRuntime().isDebuggerActive()) {
-                    finalizerTimedOut(object);
-                    break;
-                }
-            }
-        }
-
-        private Object waitForObject() {
-            while (true) {
-                Object object = FinalizerDaemon.INSTANCE.finalizingObject;
-                if (object != null) {
-                    return object;
-                }
-                synchronized (this) {
-                    // wait until something is ready to be finalized
-                    // http://code.google.com/p/android/issues/detail?id=22778
-                    try {
-                        wait();
-                    } catch (InterruptedException e) {
-                        // Daemon.stop may have interrupted us.
-                        return null;
-                    }
-                }
-            }
-        }
-
-        private void sleepFor(long startNanos, long durationNanos) {
-            while (true) {
-                long elapsedNanos = System.nanoTime() - startNanos;
-                long sleepNanos = durationNanos - elapsedNanos;
-                long sleepMills = sleepNanos / NANOS_PER_MILLI;
-                if (sleepMills <= 0) {
-                    return;
-                }
-                try {
-                    Thread.sleep(sleepMills);
-                } catch (InterruptedException e) {
-                    if (!isRunning()) {
-                        return;
-                    }
-                }
-            }
-        }
-
-        private boolean waitForFinalization(Object object) {
-            sleepFor(FinalizerDaemon.INSTANCE.finalizingStartedNanos, MAX_FINALIZE_NANOS);
-            return object != FinalizerDaemon.INSTANCE.finalizingObject;
-        }
-
-        private static void finalizerTimedOut(Object object) {
-            // The current object has exceeded the finalization deadline; abort!
-            String message = object.getClass().getName() + ".finalize() timed out after "
-                    + (MAX_FINALIZE_NANOS / NANOS_PER_SECOND) + " seconds";
-            Exception syntheticException = new TimeoutException(message);
-            // We use the stack from where finalize() was running to show where it was stuck.
-            syntheticException.setStackTrace(FinalizerDaemon.INSTANCE.getStackTrace());
-            Thread.UncaughtExceptionHandler h = Thread.getDefaultUncaughtExceptionHandler();
-            if (h == null) {
-                // If we have no handler, log and exit.
-                System.logE(message, syntheticException);
-                System.exit(2);
-            }
-            // Otherwise call the handler to do crash reporting.
-            // We don't just throw because we're not the thread that
-            // timed out; we're the thread that detected it.
-            h.uncaughtException(Thread.currentThread(), syntheticException);
-        }
-    }
-}
diff --git a/libdvm/src/main/java/java/lang/Enum.java b/libdvm/src/main/java/java/lang/Enum.java
deleted file mode 100644
index 4b897aa..0000000
--- a/libdvm/src/main/java/java/lang/Enum.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import java.io.Serializable;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import libcore.util.BasicLruCache;
-import libcore.util.EmptyArray;
-
-/**
- * The superclass of all enumerated types. Actual enumeration types inherit from
- * this class, but extending this class does not make a class an enumeration
- * type, since the compiler needs to generate special information for it.
- */
-public abstract class Enum<E extends Enum<E>> implements Serializable, Comparable<E> {
-
-    private static final long serialVersionUID = -4300926546619394005L;
-
-    private static final BasicLruCache<Class<? extends Enum>, Object[]> sharedConstantsCache
-            = new BasicLruCache<Class<? extends Enum>, Object[]>(64) {
-        @Override protected Object[] create(Class<? extends Enum> enumType) {
-            if (!enumType.isEnum()) {
-                return null;
-            }
-            Method method = (Method) Class.getDeclaredConstructorOrMethod(
-                    enumType, "values", EmptyArray.CLASS);
-            try {
-                return (Object[]) method.invoke((Object[]) null);
-            } catch (IllegalAccessException impossible) {
-                throw new AssertionError();
-            } catch (InvocationTargetException impossible) {
-                throw new AssertionError();
-            }
-        }
-    };
-
-    private final String name;
-
-    private final int ordinal;
-
-    /**
-     * Constructor for constants of enum subtypes.
-     *
-     * @param name
-     *            the enum constant's declared name.
-     * @param ordinal
-     *            the enum constant's ordinal, which corresponds to its position
-     *            in the enum declaration, starting at zero.
-     */
-    protected Enum(String name, int ordinal) {
-        this.name = name;
-        this.ordinal = ordinal;
-    }
-
-    /**
-     * Returns the name of this enum constant. The name is the field as it
-     * appears in the {@code enum} declaration.
-     *
-     * @return the name of this enum constant.
-     * @see #toString()
-     */
-    public final String name() {
-        return name;
-    }
-
-    /**
-     * Returns the position of the enum constant in the declaration. The first
-     * constant has an ordinal value of zero.
-     *
-     * @return the ordinal value of this enum constant.
-     */
-    public final int ordinal() {
-        return ordinal;
-    }
-
-    /**
-     * Returns a string containing a concise, human-readable description of this
-     * object. In this case, the enum constant's name is returned.
-     *
-     * @return a printable representation of this object.
-     */
-    @Override
-    public String toString() {
-        return name;
-    }
-
-    /**
-     * Compares this object with the specified object and indicates if they are
-     * equal. In order to be equal, {@code object} must be identical to this
-     * enum constant.
-     *
-     * @param other
-     *            the object to compare this enum constant with.
-     * @return {@code true} if the specified object is equal to this
-     *         {@code Enum}; {@code false} otherwise.
-     */
-    @Override
-    public final boolean equals(Object other) {
-        return this == other;
-    }
-
-    @Override
-    public final int hashCode() {
-        return ordinal + (name == null ? 0 : name.hashCode());
-    }
-
-    /**
-     * {@code Enum} objects are singletons, they may not be cloned. This method
-     * always throws a {@code CloneNotSupportedException}.
-     *
-     * @return does not return.
-     * @throws CloneNotSupportedException
-     *             is always thrown.
-     */
-    @Override
-    protected final Object clone() throws CloneNotSupportedException {
-        throw new CloneNotSupportedException("Enums may not be cloned");
-    }
-
-    /**
-     * Compares this object to the specified enum object to determine their
-     * relative order. This method compares the object's ordinal values, that
-     * is, their position in the enum declaration.
-     *
-     * @param o
-     *            the enum object to compare this object to.
-     * @return a negative value if the ordinal value of this enum constant is
-     *         less than the ordinal value of {@code o}; 0 if the ordinal
-     *         values of this enum constant and {@code o} are equal; a positive
-     *         value if the ordinal value of this enum constant is greater than
-     *         the ordinal value of {@code o}.
-     * @see java.lang.Comparable
-     */
-    public final int compareTo(E o) {
-        return ordinal - o.ordinal();
-    }
-
-    /**
-     * Returns the enum constant's declaring class.
-     *
-     * @return the class object representing the constant's enum type.
-     */
-    @SuppressWarnings("unchecked")
-    public final Class<E> getDeclaringClass() {
-        Class<?> myClass = getClass();
-        Class<?> mySuperClass = myClass.getSuperclass();
-        if (Enum.class == mySuperClass) {
-            return (Class<E>)myClass;
-        }
-        return (Class<E>)mySuperClass;
-    }
-
-    /**
-     * Returns the constant with the specified name of the specified enum type.
-     *
-     * @param enumType
-     *            the class of the enumerated type to search for the constant
-     *            value.
-     * @param name
-     *            the name of the constant value to find.
-     * @return the enum constant.
-     * @throws NullPointerException
-     *             if either {@code enumType} or {@code name} are {@code null}.
-     * @throws IllegalArgumentException
-     *             if {@code enumType} is not an enumerated type or does not
-     *             have a constant value called {@code name}.
-     */
-    public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
-        if (enumType == null) {
-            throw new NullPointerException("enumType == null");
-        } else if (name == null) {
-            throw new NullPointerException("name == null");
-        }
-        T[] values = getSharedConstants(enumType);
-        if (values == null) {
-            throw new IllegalArgumentException(enumType + " is not an enum type");
-        }
-        for (T value : values) {
-            if (name.equals(value.name())) {
-                return value;
-            }
-        }
-        throw new IllegalArgumentException(name + " is not a constant in " + enumType.getName());
-    }
-
-    /**
-     * Returns a shared, mutable array containing the constants of this enum. It
-     * is an error to modify the returned array.
-     *
-     * @hide
-     */
-    @SuppressWarnings("unchecked") // the cache always returns the type matching enumType
-    public static <T extends Enum<T>> T[] getSharedConstants(Class<T> enumType) {
-        return (T[]) sharedConstantsCache.get(enumType);
-    }
-
-    /**
-     * Enum types may not have finalizers.
-     *
-     * @since 1.6
-     */
-    @Override
-    @SuppressWarnings("FinalizeDoesntCallSuperFinalize")
-    protected final void finalize() {
-    }
-}
diff --git a/libdvm/src/main/java/java/lang/Object.java b/libdvm/src/main/java/java/lang/Object.java
deleted file mode 100644
index d2cd2f1..0000000
--- a/libdvm/src/main/java/java/lang/Object.java
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-/**
- * The root class of the Java class hierarchy. All non-primitive types
- * (including arrays) inherit either directly or indirectly from this class.
- *
- * <a name="writing_equals"><h4>Writing a correct {@code equals} method</h4></a>
- * <p>Follow this style to write a canonical {@code equals} method:
- * <pre>
- *   // Use @Override to avoid accidental overloading.
- *   &#x0040;Override public boolean equals(Object o) {
- *     // Return true if the objects are identical.
- *     // (This is just an optimization, not required for correctness.)
- *     if (this == o) {
- *       return true;
- *     }
- *
- *     // Return false if the other object has the wrong type.
- *     // This type may be an interface depending on the interface's specification.
- *     if (!(o instanceof MyType)) {
- *       return false;
- *     }
- *
- *     // Cast to the appropriate type.
- *     // This will succeed because of the instanceof, and lets us access private fields.
- *     MyType lhs = (MyType) o;
- *
- *     // Check each field. Primitive fields, reference fields, and nullable reference
- *     // fields are all treated differently.
- *     return primitiveField == lhs.primitiveField &amp;&amp;
- *             referenceField.equals(lhs.referenceField) &amp;&amp;
- *             (nullableField == null ? lhs.nullableField == null
- *                                    : nullableField.equals(lhs.nullableField));
- *   }
- * </pre>
- * <p>If you override {@code equals}, you should also override {@code hashCode}: equal
- * instances must have equal hash codes.
- *
- * <p>See <i>Effective Java</i> item 8 for much more detail and clarification.
- *
- * <a name="writing_hashCode"><h4>Writing a correct {@code hashCode} method</h4></a>
- * <p>Follow this style to write a canonical {@code hashCode} method:
- * <pre>
- *   &#x0040;Override public int hashCode() {
- *     // Start with a non-zero constant.
- *     int result = 17;
- *
- *     // Include a hash for each field.
- *     result = 31 * result + (booleanField ? 1 : 0);
- *
- *     result = 31 * result + byteField;
- *     result = 31 * result + charField;
- *     result = 31 * result + shortField;
- *     result = 31 * result + intField;
- *
- *     result = 31 * result + (int) (longField ^ (longField >>> 32));
- *
- *     result = 31 * result + Float.floatToIntBits(floatField);
- *
- *     long doubleFieldBits = Double.doubleToLongBits(doubleField);
- *     result = 31 * result + (int) (doubleFieldBits ^ (doubleFieldBits >>> 32));
- *
- *     result = 31 * result + Arrays.hashCode(arrayField);
- *
- *     result = 31 * result + referenceField.hashCode();
- *     result = 31 * result +
- *         (nullableReferenceField == null ? 0
- *                                         : nullableReferenceField.hashCode());
- *
- *     return result;
- *   }
- * </pre>
- *
- * <p>If you don't intend your type to be used as a hash key, don't simply rely on the default
- * {@code hashCode} implementation, because that silently and non-obviously breaks any future
- * code that does use your type as a hash key. You should throw instead:
- * <pre>
- *   &#x0040;Override public int hashCode() {
- *     throw new UnsupportedOperationException();
- *   }
- * </pre>
- *
- * <p>See <i>Effective Java</i> item 9 for much more detail and clarification.
- *
- * <a name="writing_toString"><h4>Writing a useful {@code toString} method</h4></a>
- * <p>For debugging convenience, it's common to override {@code toString} in this style:
- * <pre>
- *   &#x0040;Override public String toString() {
- *     return getClass().getName() + "[" +
- *         "primitiveField=" + primitiveField + ", " +
- *         "referenceField=" + referenceField + ", " +
- *         "arrayField=" + Arrays.toString(arrayField) + "]";
- *   }
- * </pre>
- * <p>The set of fields to include is generally the same as those that would be tested
- * in your {@code equals} implementation.
- * <p>See <i>Effective Java</i> item 10 for much more detail and clarification.
- */
-public class Object {
-    /**
-     * Constructs a new instance of {@code Object}.
-     */
-    public Object() {
-    }
-
-    /**
-     * Creates and returns a copy of this {@code Object}. The default
-     * implementation returns a so-called "shallow" copy: It creates a new
-     * instance of the same class and then copies the field values (including
-     * object references) from this instance to the new instance. A "deep" copy,
-     * in contrast, would also recursively clone nested objects. A subclass that
-     * needs to implement this kind of cloning should call {@code super.clone()}
-     * to create the new instance and then create deep copies of the nested,
-     * mutable objects.
-     *
-     * @return a copy of this object.
-     * @throws CloneNotSupportedException
-     *             if this object's class does not implement the {@code
-     *             Cloneable} interface.
-     */
-    protected Object clone() throws CloneNotSupportedException {
-        if (!(this instanceof Cloneable)) {
-            throw new CloneNotSupportedException("Class doesn't implement Cloneable");
-        }
-
-        return internalClone((Cloneable) this);
-    }
-
-    /*
-     * Native helper method for cloning.
-     */
-    private native Object internalClone(Cloneable o);
-
-    /**
-     * Compares this instance with the specified object and indicates if they
-     * are equal. In order to be equal, {@code o} must represent the same object
-     * as this instance using a class-specific comparison. The general contract
-     * is that this comparison should be reflexive, symmetric, and transitive.
-     * Also, no object reference other than null is equal to null.
-     *
-     * <p>The default implementation returns {@code true} only if {@code this ==
-     * o}. See <a href="{@docRoot}reference/java/lang/Object.html#writing_equals">Writing a correct
-     * {@code equals} method</a>
-     * if you intend implementing your own {@code equals} method.
-     *
-     * <p>The general contract for the {@code equals} and {@link
-     * #hashCode()} methods is that if {@code equals} returns {@code true} for
-     * any two objects, then {@code hashCode()} must return the same value for
-     * these objects. This means that subclasses of {@code Object} usually
-     * override either both methods or neither of them.
-     *
-     * @param o
-     *            the object to compare this instance with.
-     * @return {@code true} if the specified object is equal to this {@code
-     *         Object}; {@code false} otherwise.
-     * @see #hashCode
-     */
-    public boolean equals(Object o) {
-        return this == o;
-    }
-
-    /**
-     * Invoked when the garbage collector has detected that this instance is no longer reachable.
-     * The default implementation does nothing, but this method can be overridden to free resources.
-     *
-     * <p>Note that objects that override {@code finalize} are significantly more expensive than
-     * objects that don't. Finalizers may be run a long time after the object is no longer
-     * reachable, depending on memory pressure, so it's a bad idea to rely on them for cleanup.
-     * Note also that finalizers are run on a single VM-wide finalizer thread,
-     * so doing blocking work in a finalizer is a bad idea. A finalizer is usually only necessary
-     * for a class that has a native peer and needs to call a native method to destroy that peer.
-     * Even then, it's better to provide an explicit {@code close} method (and implement
-     * {@link java.io.Closeable}), and insist that callers manually dispose of instances. This
-     * works well for something like files, but less well for something like a {@code BigInteger}
-     * where typical calling code would have to deal with lots of temporaries. Unfortunately,
-     * code that creates lots of temporaries is the worst kind of code from the point of view of
-     * the single finalizer thread.
-     *
-     * <p>If you <i>must</i> use finalizers, consider at least providing your own
-     * {@link java.lang.ref.ReferenceQueue} and having your own thread process that queue.
-     *
-     * <p>Unlike constructors, finalizers are not automatically chained. You are responsible for
-     * calling {@code super.finalize()} yourself.
-     *
-     * <p>Uncaught exceptions thrown by finalizers are ignored and do not terminate the finalizer
-     * thread.
-     *
-     * See <i>Effective Java</i> Item 7, "Avoid finalizers" for more.
-     */
-    @FindBugsSuppressWarnings("FI_EMPTY")
-    protected void finalize() throws Throwable {
-    }
-
-    /**
-     * Returns the unique instance of {@link Class} that represents this
-     * object's class. Note that {@code getClass()} is a special case in that it
-     * actually returns {@code Class<? extends Foo>} where {@code Foo} is the
-     * erasure of the type of the expression {@code getClass()} was called upon.
-     * <p>
-     * As an example, the following code actually compiles, although one might
-     * think it shouldn't:
-     * <p>
-     * <pre>{@code
-     *   List<Integer> l = new ArrayList<Integer>();
-     *   Class<? extends List> c = l.getClass();}</pre>
-     *
-     * @return this object's {@code Class} instance.
-     */
-    public final native Class<?> getClass();
-
-    /**
-     * Returns an integer hash code for this object. By contract, any two
-     * objects for which {@link #equals} returns {@code true} must return
-     * the same hash code value. This means that subclasses of {@code Object}
-     * usually override both methods or neither method.
-     *
-     * <p>Note that hash values must not change over time unless information used in equals
-     * comparisons also changes.
-     *
-     * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_hashCode">Writing a correct
-     * {@code hashCode} method</a>
-     * if you intend implementing your own {@code hashCode} method.
-     *
-     * @return this object's hash code.
-     * @see #equals
-     */
-    public native int hashCode();
-
-    /**
-     * Causes a thread which is waiting on this object's monitor (by means of
-     * calling one of the {@code wait()} methods) to be woken up. If more than
-     * one thread is waiting, one of them is chosen at the discretion of the
-     * VM. The chosen thread will not run immediately. The thread
-     * that called {@code notify()} has to release the object's monitor first.
-     * Also, the chosen thread still has to compete against other threads that
-     * try to synchronize on the same object.
-     *
-     * <p>This method can only be invoked by a thread which owns this object's
-     * monitor. A thread becomes owner of an object's monitor
-     * <ul>
-     * <li>by executing a synchronized method of that object;</li>
-     * <li>by executing the body of a {@code synchronized} statement that
-     * synchronizes on the object;</li>
-     * <li>by executing a synchronized static method if the object is of type
-     * {@code Class}.</li>
-     * </ul>
-     *
-     * @see #notifyAll
-     * @see #wait()
-     * @see #wait(long)
-     * @see #wait(long,int)
-     * @see java.lang.Thread
-     */
-    public final native void notify();
-
-    /**
-     * Causes all threads which are waiting on this object's monitor (by means
-     * of calling one of the {@code wait()} methods) to be woken up. The threads
-     * will not run immediately. The thread that called {@code notify()} has to
-     * release the object's monitor first. Also, the threads still have to
-     * compete against other threads that try to synchronize on the same object.
-     *
-     * <p>This method can only be invoked by a thread which owns this object's
-     * monitor. A thread becomes owner of an object's monitor
-     * <ul>
-     * <li>by executing a synchronized method of that object;</li>
-     * <li>by executing the body of a {@code synchronized} statement that
-     * synchronizes on the object;</li>
-     * <li>by executing a synchronized static method if the object is of type
-     * {@code Class}.</li>
-     * </ul>
-     *
-     * @throws IllegalMonitorStateException
-     *             if the thread calling this method is not the owner of this
-     *             object's monitor.
-     * @see #notify
-     * @see #wait()
-     * @see #wait(long)
-     * @see #wait(long,int)
-     * @see java.lang.Thread
-     */
-    public final native void notifyAll();
-
-    /**
-     * Returns a string containing a concise, human-readable description of this
-     * object. Subclasses are encouraged to override this method and provide an
-     * implementation that takes into account the object's type and data. The
-     * default implementation is equivalent to the following expression:
-     * <pre>
-     *   getClass().getName() + '@' + Integer.toHexString(hashCode())</pre>
-     * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_toString">Writing a useful
-     * {@code toString} method</a>
-     * if you intend implementing your own {@code toString} method.
-     *
-     * @return a printable representation of this object.
-     */
-    public String toString() {
-        return getClass().getName() + '@' + Integer.toHexString(hashCode());
-    }
-
-    /**
-     * Causes the calling thread to wait until another thread calls the {@code
-     * notify()} or {@code notifyAll()} method of this object. This method can
-     * only be invoked by a thread which owns this object's monitor; see
-     * {@link #notify()} on how a thread can become the owner of a monitor.
-     *
-     * <p>A waiting thread can be sent {@code interrupt()} to cause it to
-     * prematurely stop waiting, so {@code wait} should be called in a loop to
-     * check that the condition that has been waited for has been met before
-     * continuing.
-     *
-     * <p>While the thread waits, it gives up ownership of this object's
-     * monitor. When it is notified (or interrupted), it re-acquires the monitor
-     * before it starts running.
-     *
-     * @throws IllegalMonitorStateException
-     *             if the thread calling this method is not the owner of this
-     *             object's monitor.
-     * @throws InterruptedException if the current thread has been interrupted.
-     *             The interrupted status of the current thread will be cleared before the exception
-     *             is thrown.
-     * @see #notify
-     * @see #notifyAll
-     * @see #wait(long)
-     * @see #wait(long,int)
-     * @see java.lang.Thread
-     */
-    public final void wait() throws InterruptedException {
-        wait(0, 0);
-    }
-
-    /**
-     * Causes the calling thread to wait until another thread calls the {@code
-     * notify()} or {@code notifyAll()} method of this object or until the
-     * specified timeout expires. This method can only be invoked by a thread
-     * which owns this object's monitor; see {@link #notify()} on how a thread
-     * can become the owner of a monitor.
-     *
-     * <p>A waiting thread can be sent {@code interrupt()} to cause it to
-     * prematurely stop waiting, so {@code wait} should be called in a loop to
-     * check that the condition that has been waited for has been met before
-     * continuing.
-     *
-     * <p>While the thread waits, it gives up ownership of this object's
-     * monitor. When it is notified (or interrupted), it re-acquires the monitor
-     * before it starts running.
-     *
-     * <p>A timeout of zero means the calling thread should wait forever unless interrupted or
-     * notified.
-     *
-     * @param millis
-     *            the maximum time to wait in milliseconds.
-     * @throws IllegalArgumentException
-     *             if {@code millis < 0}.
-     * @throws IllegalMonitorStateException
-     *             if the thread calling this method is not the owner of this
-     *             object's monitor.
-     * @throws InterruptedException if the current thread has been interrupted.
-     *             The interrupted status of the current thread will be cleared before the exception
-     *             is thrown.
-     * @see #notify
-     * @see #notifyAll
-     * @see #wait()
-     * @see #wait(long,int)
-     * @see java.lang.Thread
-     */
-    public final void wait(long millis) throws InterruptedException {
-        wait(millis, 0);
-    }
-
-    /**
-     * Causes the calling thread to wait until another thread calls the {@code
-     * notify()} or {@code notifyAll()} method of this object or until the
-     * specified timeout expires. This method can only be invoked by a thread
-     * that owns this object's monitor; see {@link #notify()} on how a thread
-     * can become the owner of a monitor.
-     *
-     * <p>A waiting thread can be sent {@code interrupt()} to cause it to
-     * prematurely stop waiting, so {@code wait} should be called in a loop to
-     * check that the condition that has been waited for has been met before
-     * continuing.
-     *
-     * <p>While the thread waits, it gives up ownership of this object's
-     * monitor. When it is notified (or interrupted), it re-acquires the monitor
-     * before it starts running.
-     *
-     * <p>A timeout of zero means the calling thread should wait forever unless interrupted or
-     * notified.
-     *
-     * @param millis
-     *            the maximum time to wait in milliseconds.
-     * @param nanos
-     *            the fraction of a millisecond to wait, specified in
-     *            nanoseconds.
-     * @throws IllegalArgumentException
-     *             if {@code millis < 0}, {@code nanos < 0} or {@code nanos >
-     *             999999}.
-     * @throws IllegalMonitorStateException
-     *             if the thread calling this method is not the owner of this
-     *             object's monitor.
-     * @throws InterruptedException if the current thread has been interrupted.
-     *             The interrupted status of the current thread will be cleared before the exception
-     *             is thrown.
-     * @see #notify
-     * @see #notifyAll
-     * @see #wait()
-     * @see #wait(long,int)
-     * @see java.lang.Thread
-     */
-    public final native void wait(long millis, int nanos) throws InterruptedException;
-}
diff --git a/libdvm/src/main/java/java/lang/String.java b/libdvm/src/main/java/java/lang/String.java
deleted file mode 100644
index 10a6301..0000000
--- a/libdvm/src/main/java/java/lang/String.java
+++ /dev/null
@@ -1,2075 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package java.lang;
-
-import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-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.EmptyArray;
-
-/**
- * An immutable sequence of characters/code units ({@code char}s). A
- * {@code String} is represented by array of UTF-16 values, such that
- * Unicode supplementary characters (code points) are stored/encoded as
- * surrogate pairs via Unicode code units ({@code char}).
- *
- * <a name="backing_array"><h3>Backing Arrays</h3></a>
- * This class is implemented using a char[]. The length of the array may exceed
- * the length of the string. For example, the string "Hello" may be backed by
- * the array {@code ['H', 'e', 'l', 'l', 'o', 'W'. 'o', 'r', 'l', 'd']} with
- * offset 0 and length 5.
- *
- * <p>Multiple strings can share the same char[] because strings are immutable.
- * The {@link #substring} method <strong>always</strong> returns a string that
- * shares the backing array of its source string. Generally this is an
- * optimization: fewer character arrays need to be allocated, and less copying
- * is necessary. But this can also lead to unwanted heap retention. Taking a
- * short substring of long string means that the long shared char[] won't be
- * garbage until both strings are garbage. This typically happens when parsing
- * small substrings out of a large input. To avoid this where necessary, call
- * {@code new String(longString.subString(...))}. The string copy constructor
- * always ensures that the backing array is no larger than necessary.
- *
- * @see StringBuffer
- * @see StringBuilder
- * @see Charset
- * @since 1.0
- */
-public final class String implements Serializable, Comparable<String>, CharSequence {
-
-    private static final long serialVersionUID = -6849794470754667710L;
-
-    private static final char REPLACEMENT_CHAR = (char) 0xfffd;
-
-    /**
-     * CaseInsensitiveComparator compares Strings ignoring the case of the
-     * characters.
-     */
-    private static final class CaseInsensitiveComparator implements
-            Comparator<String>, Serializable {
-        private static final long serialVersionUID = 8575799808933029326L;
-
-        /**
-         * Compare the two objects to determine the relative ordering.
-         *
-         * @param o1
-         *            an Object to compare
-         * @param o2
-         *            an Object to compare
-         * @return an int < 0 if object1 is less than object2, 0 if they are
-         *         equal, and > 0 if object1 is greater
-         *
-         * @throws ClassCastException
-         *                if objects are not the correct type
-         */
-        public int compare(String o1, String o2) {
-            return o1.compareToIgnoreCase(o2);
-        }
-    }
-
-    /**
-     * A comparator ignoring the case of the characters.
-     */
-    public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
-
-    private static final char[] ASCII;
-    static {
-        ASCII = new char[128];
-        for (int i = 0; i < ASCII.length; ++i) {
-            ASCII[i] = (char) i;
-        }
-    }
-
-    private final char[] value;
-
-    private final int offset;
-
-    private final int count;
-
-    private int hashCode;
-
-    /**
-     * Creates an empty string.
-     */
-    public String() {
-        value = EmptyArray.CHAR;
-        offset = 0;
-        count = 0;
-    }
-
-    /*
-     * Private constructor used for JIT optimization.
-     */
-    @SuppressWarnings("unused")
-    private String(String s, char c) {
-        offset = 0;
-        value = new char[s.count + 1];
-        count = s.count + 1;
-        System.arraycopy(s.value, s.offset, value, 0, s.count);
-        value[s.count] = c;
-    }
-
-    /**
-     * Converts the byte array to a string using the system's
-     * {@link java.nio.charset.Charset#defaultCharset default charset}.
-     */
-    @FindBugsSuppressWarnings("DM_DEFAULT_ENCODING")
-    public String(byte[] data) {
-        this(data, 0, data.length);
-    }
-
-    /**
-     * Converts the byte array to a string, setting the high byte of every
-     * character to the specified value.
-     *
-     * @param data
-     *            the byte array to convert to a string.
-     * @param high
-     *            the high byte to use.
-     * @throws NullPointerException
-     *             if {@code data == null}.
-     * @deprecated Use {@link #String(byte[])} or {@link #String(byte[], String)} instead.
-     */
-    @Deprecated
-    public String(byte[] data, int high) {
-        this(data, high, 0, data.length);
-    }
-
-    /**
-     * Converts a subsequence of the byte array to a string using the system's
-     * {@link java.nio.charset.Charset#defaultCharset default charset}.
-     *
-     * @throws NullPointerException
-     *             if {@code data == null}.
-     * @throws IndexOutOfBoundsException
-     *             if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}.
-     */
-    public String(byte[] data, int offset, int byteCount) {
-        this(data, offset, byteCount, Charset.defaultCharset());
-    }
-
-    /**
-     * Converts the byte array to a string, setting the high byte of every
-     * character to {@code high}.
-     *
-     * @throws NullPointerException
-     *             if {@code data == null}.
-     * @throws IndexOutOfBoundsException
-     *             if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}
-     *
-     * @deprecated Use {@link #String(byte[], int, int)} instead.
-     */
-    @Deprecated
-    public String(byte[] data, int high, int offset, int byteCount) {
-        if ((offset | byteCount) < 0 || byteCount > data.length - offset) {
-            throw failedBoundsCheck(data.length, offset, byteCount);
-        }
-        this.offset = 0;
-        this.value = new char[byteCount];
-        this.count = byteCount;
-        high <<= 8;
-        for (int i = 0; i < count; i++) {
-            value[i] = (char) (high + (data[offset++] & 0xff));
-        }
-    }
-
-    /**
-     * Converts the byte array to a string using the named charset.
-     *
-     * <p>The behavior when the bytes cannot be decoded by the named charset
-     * is unspecified. Use {@link java.nio.charset.CharsetDecoder} for more control.
-     *
-     * @throws NullPointerException
-     *             if {@code data == null}.
-     * @throws IndexOutOfBoundsException
-     *             if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}.
-     * @throws UnsupportedEncodingException
-     *             if the named charset is not supported.
-     */
-    public String(byte[] data, int offset, int byteCount, String charsetName) throws UnsupportedEncodingException {
-        this(data, offset, byteCount, Charset.forNameUEE(charsetName));
-    }
-
-    /**
-     * Converts the byte array to a string using the named charset.
-     *
-     * <p>The behavior when the bytes cannot be decoded by the named charset
-     * is unspecified. Use {@link java.nio.charset.CharsetDecoder} for more control.
-     *
-     * @throws NullPointerException
-     *             if {@code data == null}.
-     * @throws UnsupportedEncodingException
-     *             if {@code charsetName} is not supported.
-     */
-    public String(byte[] data, String charsetName) throws UnsupportedEncodingException {
-        this(data, 0, data.length, Charset.forNameUEE(charsetName));
-    }
-
-    /**
-     * Converts the byte array to a string using the given charset.
-     *
-     * <p>The behavior when the bytes cannot be decoded by the given charset
-     * is to replace malformed input and unmappable characters with the charset's default
-     * replacement string. Use {@link java.nio.charset.CharsetDecoder} for more control.
-     *
-     * @throws IndexOutOfBoundsException
-     *             if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}
-     * @throws NullPointerException
-     *             if {@code data == null}
-     *
-     * @since 1.6
-     */
-    public String(byte[] data, int offset, int byteCount, Charset charset) {
-        if ((offset | byteCount) < 0 || byteCount > data.length - offset) {
-            throw failedBoundsCheck(data.length, offset, byteCount);
-        }
-
-        // We inline UTF-8, ISO-8859-1, and US-ASCII decoders for speed and because 'count' and
-        // 'value' are final.
-        String canonicalCharsetName = charset.name();
-        if (canonicalCharsetName.equals("UTF-8")) {
-            byte[] d = data;
-            char[] v = new char[byteCount];
-
-            int idx = offset;
-            int last = offset + byteCount;
-            int s = 0;
-outer:
-            while (idx < last) {
-                byte b0 = d[idx++];
-                if ((b0 & 0x80) == 0) {
-                    // 0xxxxxxx
-                    // Range:  U-00000000 - U-0000007F
-                    int val = b0 & 0xff;
-                    v[s++] = (char) val;
-                } else if (((b0 & 0xe0) == 0xc0) || ((b0 & 0xf0) == 0xe0) ||
-                        ((b0 & 0xf8) == 0xf0) || ((b0 & 0xfc) == 0xf8) || ((b0 & 0xfe) == 0xfc)) {
-                    int utfCount = 1;
-                    if ((b0 & 0xf0) == 0xe0) utfCount = 2;
-                    else if ((b0 & 0xf8) == 0xf0) utfCount = 3;
-                    else if ((b0 & 0xfc) == 0xf8) utfCount = 4;
-                    else if ((b0 & 0xfe) == 0xfc) utfCount = 5;
-
-                    // 110xxxxx (10xxxxxx)+
-                    // Range:  U-00000080 - U-000007FF (count == 1)
-                    // Range:  U-00000800 - U-0000FFFF (count == 2)
-                    // Range:  U-00010000 - U-001FFFFF (count == 3)
-                    // Range:  U-00200000 - U-03FFFFFF (count == 4)
-                    // Range:  U-04000000 - U-7FFFFFFF (count == 5)
-
-                    if (idx + utfCount > last) {
-                        v[s++] = REPLACEMENT_CHAR;
-                        continue;
-                    }
-
-                    // Extract usable bits from b0
-                    int val = b0 & (0x1f >> (utfCount - 1));
-                    for (int i = 0; i < utfCount; ++i) {
-                        byte b = d[idx++];
-                        if ((b & 0xc0) != 0x80) {
-                            v[s++] = REPLACEMENT_CHAR;
-                            idx--; // Put the input char back
-                            continue outer;
-                        }
-                        // Push new bits in from the right side
-                        val <<= 6;
-                        val |= b & 0x3f;
-                    }
-
-                    // Note: Java allows overlong char
-                    // specifications To disallow, check that val
-                    // is greater than or equal to the minimum
-                    // value for each count:
-                    //
-                    // count    min value
-                    // -----   ----------
-                    //   1           0x80
-                    //   2          0x800
-                    //   3        0x10000
-                    //   4       0x200000
-                    //   5      0x4000000
-
-                    // Allow surrogate values (0xD800 - 0xDFFF) to
-                    // be specified using 3-byte UTF values only
-                    if ((utfCount != 2) && (val >= 0xD800) && (val <= 0xDFFF)) {
-                        v[s++] = REPLACEMENT_CHAR;
-                        continue;
-                    }
-
-                    // Reject chars greater than the Unicode maximum of U+10FFFF.
-                    if (val > 0x10FFFF) {
-                        v[s++] = REPLACEMENT_CHAR;
-                        continue;
-                    }
-
-                    // Encode chars from U+10000 up as surrogate pairs
-                    if (val < 0x10000) {
-                        v[s++] = (char) val;
-                    } else {
-                        int x = val & 0xffff;
-                        int u = (val >> 16) & 0x1f;
-                        int w = (u - 1) & 0xffff;
-                        int hi = 0xd800 | (w << 6) | (x >> 10);
-                        int lo = 0xdc00 | (x & 0x3ff);
-                        v[s++] = (char) hi;
-                        v[s++] = (char) lo;
-                    }
-                } else {
-                    // Illegal values 0x8*, 0x9*, 0xa*, 0xb*, 0xfd-0xff
-                    v[s++] = REPLACEMENT_CHAR;
-                }
-            }
-
-            if (s == byteCount) {
-                // We guessed right, so we can use our temporary array as-is.
-                this.offset = 0;
-                this.value = v;
-                this.count = s;
-            } else {
-                // Our temporary array was too big, so reallocate and copy.
-                this.offset = 0;
-                this.value = new char[s];
-                this.count = s;
-                System.arraycopy(v, 0, value, 0, s);
-            }
-        } else if (canonicalCharsetName.equals("ISO-8859-1")) {
-            this.offset = 0;
-            this.value = new char[byteCount];
-            this.count = byteCount;
-            Charsets.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);
-        } else {
-            CharBuffer cb = charset.decode(ByteBuffer.wrap(data, offset, byteCount));
-            this.offset = 0;
-            this.count = cb.length();
-            if (count > 0) {
-                // We could use cb.array() directly, but that would mean we'd have to trust
-                // the CharsetDecoder doesn't hang on to the CharBuffer and mutate it later,
-                // which would break String's immutability guarantee. It would also tend to
-                // mean that we'd be wasting memory because CharsetDecoder doesn't trim the
-                // array. So we copy.
-                this.value = new char[count];
-                System.arraycopy(cb.array(), 0, value, 0, count);
-            } else {
-                this.value = EmptyArray.CHAR;
-            }
-        }
-    }
-
-    /**
-     * Converts the byte array to a String using the given charset.
-     *
-     * @throws NullPointerException if {@code data == null}
-     * @since 1.6
-     */
-    public String(byte[] data, Charset charset) {
-        this(data, 0, data.length, charset);
-    }
-
-    /**
-     * Initializes this string to contain the characters in the specified
-     * character array. Modifying the character array after creating the string
-     * has no effect on the string.
-     *
-     * @throws NullPointerException if {@code data == null}
-     */
-    public String(char[] data) {
-        this(data, 0, data.length);
-    }
-
-    /**
-     * Initializes this string to contain the specified characters in the
-     * character array. Modifying the character array after creating the string
-     * has no effect on the string.
-     *
-     * @throws NullPointerException
-     *             if {@code data == null}.
-     * @throws IndexOutOfBoundsException
-     *             if {@code charCount < 0 || offset < 0 || offset + charCount > data.length}
-     */
-    public String(char[] data, int offset, int charCount) {
-        if ((offset | charCount) < 0 || charCount > data.length - offset) {
-            throw failedBoundsCheck(data.length, offset, charCount);
-        }
-        this.offset = 0;
-        this.value = new char[charCount];
-        this.count = charCount;
-        System.arraycopy(data, offset, value, 0, count);
-    }
-
-    /*
-     * Internal version of the String(char[], int, int) constructor.
-     * Does not range check, null check, or copy the character array.
-     */
-    String(int offset, int charCount, char[] chars) {
-        this.value = chars;
-        this.offset = offset;
-        this.count = charCount;
-    }
-
-    /**
-     * Constructs a new string with the same sequence of characters as {@code
-     * toCopy}. The returned string's <a href="#backing_array">backing array</a>
-     * is no larger than necessary.
-     */
-    public String(String toCopy) {
-        value = (toCopy.value.length == toCopy.count)
-                ? toCopy.value
-                : Arrays.copyOfRange(toCopy.value, toCopy.offset, toCopy.offset + toCopy.length());
-        offset = 0;
-        count = value.length;
-    }
-
-    /*
-     * Private constructor useful for JIT optimization.
-     */
-    @SuppressWarnings( { "unused", "nls" })
-    private String(String s1, String s2) {
-        if (s1 == null) {
-            s1 = "null";
-        }
-        if (s2 == null) {
-            s2 = "null";
-        }
-        count = s1.count + s2.count;
-        value = new char[count];
-        offset = 0;
-        System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
-        System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
-    }
-
-    /*
-     * Private constructor useful for JIT optimization.
-     */
-    @SuppressWarnings( { "unused", "nls" })
-    private String(String s1, String s2, String s3) {
-        if (s1 == null) {
-            s1 = "null";
-        }
-        if (s2 == null) {
-            s2 = "null";
-        }
-        if (s3 == null) {
-            s3 = "null";
-        }
-        count = s1.count + s2.count + s3.count;
-        value = new char[count];
-        offset = 0;
-        System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
-        System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
-        System.arraycopy(s3.value, s3.offset, value, s1.count + s2.count, s3.count);
-    }
-
-    /**
-     * Creates a {@code String} from the contents of the specified
-     * {@code StringBuffer}.
-     */
-    public String(StringBuffer stringBuffer) {
-        offset = 0;
-        synchronized (stringBuffer) {
-            value = stringBuffer.shareValue();
-            count = stringBuffer.length();
-        }
-    }
-
-    /**
-     * Creates a {@code String} from the sub-array of Unicode code points.
-     *
-     * @throws NullPointerException
-     *             if {@code codePoints == null}.
-     * @throws IllegalArgumentException
-     *             if any of the elements of {@code codePoints} are not valid
-     *             Unicode code points.
-     * @throws IndexOutOfBoundsException
-     *             if {@code offset} or {@code count} are not within the bounds
-     *             of {@code codePoints}.
-     * @since 1.5
-     */
-    public String(int[] codePoints, int offset, int count) {
-        if (codePoints == null) {
-            throw new NullPointerException("codePoints == null");
-        }
-        if ((offset | count) < 0 || count > codePoints.length - offset) {
-            throw failedBoundsCheck(codePoints.length, offset, count);
-        }
-        this.offset = 0;
-        this.value = new char[count * 2];
-        int end = offset + count;
-        int c = 0;
-        for (int i = offset; i < end; i++) {
-            c += Character.toChars(codePoints[i], this.value, c);
-        }
-        this.count = c;
-    }
-
-    /**
-     * Creates a {@code String} from the contents of the specified {@code
-     * StringBuilder}.
-     *
-     * @throws NullPointerException
-     *             if {@code stringBuilder == null}.
-     * @since 1.5
-     */
-    public String(StringBuilder stringBuilder) {
-        if (stringBuilder == null) {
-            throw new NullPointerException("stringBuilder == null");
-        }
-        this.offset = 0;
-        this.count = stringBuilder.length();
-        this.value = new char[this.count];
-        stringBuilder.getChars(0, this.count, this.value, 0);
-    }
-
-    /*
-     * Creates a {@code String} that is s1 + v1. May be used by JIT code.
-     */
-    @SuppressWarnings("unused")
-    private String(String s1, int v1) {
-        if (s1 == null) {
-            s1 = "null";
-        }
-        String s2 = String.valueOf(v1);
-        int len = s1.count + s2.count;
-        value = new char[len];
-        offset = 0;
-        System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
-        System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
-        count = len;
-    }
-
-    /**
-     * Returns the character at {@code index}.
-     * @throws IndexOutOfBoundsException if {@code index < 0} or {@code index >= length()}.
-     */
-    public char charAt(int index) {
-        if (index < 0 || index >= count) {
-            throw indexAndLength(index);
-        }
-        return value[offset + index];
-    }
-
-    private StringIndexOutOfBoundsException indexAndLength(int index) {
-        throw new StringIndexOutOfBoundsException(this, index);
-    }
-
-    private StringIndexOutOfBoundsException startEndAndLength(int start, int end) {
-        throw new StringIndexOutOfBoundsException(this, start, end - start);
-    }
-
-    private StringIndexOutOfBoundsException failedBoundsCheck(int arrayLength, int offset, int count) {
-        throw new StringIndexOutOfBoundsException(arrayLength, offset, count);
-    }
-
-    /**
-     * This isn't equivalent to either of ICU's u_foldCase case folds, and thus any of the Unicode
-     * case folds, but it's what the RI uses.
-     */
-    private char foldCase(char ch) {
-        if (ch < 128) {
-            if ('A' <= ch && ch <= 'Z') {
-                return (char) (ch + ('a' - 'A'));
-            }
-            return ch;
-        }
-        return Character.toLowerCase(Character.toUpperCase(ch));
-    }
-
-    /**
-     * Compares the specified string to this string using the Unicode values of
-     * the characters. Returns 0 if the strings contain the same characters in
-     * the same order. Returns a negative integer if the first non-equal
-     * character in this string has a Unicode value which is less than the
-     * Unicode value of the character at the same position in the specified
-     * string, or if this string is a prefix of the specified string. Returns a
-     * positive integer if the first non-equal character in this string has a
-     * Unicode value which is greater than the Unicode value of the character at
-     * the same position in the specified string, or if the specified string is
-     * a prefix of this string.
-     *
-     * @param string
-     *            the string to compare.
-     * @return 0 if the strings are equal, a negative integer if this string is
-     *         before the specified string, or a positive integer if this string
-     *         is after the specified string.
-     * @throws NullPointerException
-     *             if {@code string} is {@code null}.
-     */
-    public native int compareTo(String string);
-
-    /**
-     * Compares the specified string to this string using the Unicode values of
-     * the characters, ignoring case differences. Returns 0 if the strings
-     * contain the same characters in the same order. Returns a negative integer
-     * if the first non-equal character in this string has a Unicode value which
-     * is less than the Unicode value of the character at the same position in
-     * the specified string, or if this string is a prefix of the specified
-     * string. Returns a positive integer if the first non-equal character in
-     * this string has a Unicode value which is greater than the Unicode value
-     * of the character at the same position in the specified string, or if the
-     * specified string is a prefix of this string.
-     *
-     * @param string
-     *            the string to compare.
-     * @return 0 if the strings are equal, a negative integer if this string is
-     *         before the specified string, or a positive integer if this string
-     *         is after the specified string.
-     * @throws NullPointerException
-     *             if {@code string} is {@code null}.
-     */
-    public int compareToIgnoreCase(String string) {
-        int o1 = offset, o2 = string.offset, result;
-        int end = offset + (count < string.count ? count : string.count);
-        char c1, c2;
-        char[] target = string.value;
-        while (o1 < end) {
-            if ((c1 = value[o1++]) == (c2 = target[o2++])) {
-                continue;
-            }
-            c1 = foldCase(c1);
-            c2 = foldCase(c2);
-            if ((result = c1 - c2) != 0) {
-                return result;
-            }
-        }
-        return count - string.count;
-    }
-
-    /**
-     * Concatenates this string and the specified string.
-     *
-     * @param string
-     *            the string to concatenate
-     * @return a new string which is the concatenation of this string and the
-     *         specified string.
-     */
-    public String concat(String string) {
-        if (string.count > 0 && count > 0) {
-            char[] buffer = new char[count + string.count];
-            System.arraycopy(value, offset, buffer, 0, count);
-            System.arraycopy(string.value, string.offset, buffer, count, string.count);
-            return new String(0, buffer.length, buffer);
-        }
-        return count == 0 ? string : this;
-    }
-
-    /**
-     * Creates a new string containing the characters in the specified character
-     * array. Modifying the character array after creating the string has no
-     * effect on the string.
-     *
-     * @param data
-     *            the array of characters.
-     * @return the new string.
-     * @throws NullPointerException
-     *             if {@code data} is {@code null}.
-     */
-    public static String copyValueOf(char[] data) {
-        return new String(data, 0, data.length);
-    }
-
-    /**
-     * Creates a new string containing the specified characters in the character
-     * array. Modifying the character array after creating the string has no
-     * effect on the string.
-     *
-     * @param data
-     *            the array of characters.
-     * @param start
-     *            the starting offset in the character array.
-     * @param length
-     *            the number of characters to use.
-     * @return the new string.
-     * @throws NullPointerException
-     *             if {@code data} is {@code null}.
-     * @throws IndexOutOfBoundsException
-     *             if {@code length < 0, start < 0} or {@code start + length >
-     *             data.length}.
-     */
-    public static String copyValueOf(char[] data, int start, int length) {
-        return new String(data, start, length);
-    }
-
-    /**
-     * Compares the specified string to this string to determine if the
-     * specified string is a suffix.
-     *
-     * @param suffix
-     *            the suffix to look for.
-     * @return {@code true} if the specified string is a suffix of this string,
-     *         {@code false} otherwise.
-     * @throws NullPointerException
-     *             if {@code suffix} is {@code null}.
-     */
-    public boolean endsWith(String suffix) {
-        return regionMatches(count - suffix.count, suffix, 0, suffix.count);
-    }
-
-    /**
-     * Compares the specified object to this string and returns true if they are
-     * equal. The object must be an instance of string with the same characters
-     * in the same order.
-     *
-     * @param other
-     *            the object to compare.
-     * @return {@code true} if the specified object is equal to this string,
-     *         {@code false} otherwise.
-     * @see #hashCode
-     */
-    @Override public boolean equals(Object other) {
-        if (other == this) {
-          return true;
-        }
-        if (other instanceof String) {
-            String s = (String)other;
-            int count = this.count;
-            if (s.count != count) {
-                return false;
-            }
-            // TODO: we want to avoid many boundchecks in the loop below
-            // for long Strings until we have array equality intrinsic.
-            // Bad benchmarks just push .equals without first getting a
-            // hashCode hit (unlike real world use in a Hashtable). Filter
-            // out these long strings here. When we get the array equality
-            // intrinsic then remove this use of hashCode.
-            if (hashCode() != s.hashCode()) {
-                return false;
-            }
-            char[] value1 = value;
-            int offset1 = offset;
-            char[] value2 = s.value;
-            int offset2 = s.offset;
-            for (int end = offset1 + count; offset1 < end; ) {
-                if (value1[offset1] != value2[offset2]) {
-                    return false;
-                }
-                offset1++;
-                offset2++;
-            }
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Compares the specified string to this string ignoring the case of the
-     * characters and returns true if they are equal.
-     *
-     * @param string
-     *            the string to compare.
-     * @return {@code true} if the specified string is equal to this string,
-     *         {@code false} otherwise.
-     */
-    @FindBugsSuppressWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ")
-    public boolean equalsIgnoreCase(String string) {
-        if (string == this) {
-            return true;
-        }
-        if (string == null || count != string.count) {
-            return false;
-        }
-        int o1 = offset, o2 = string.offset;
-        int end = offset + count;
-        char[] target = string.value;
-        while (o1 < end) {
-            char c1 = value[o1++];
-            char c2 = target[o2++];
-            if (c1 != c2 && foldCase(c1) != foldCase(c2)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Mangles this string into a byte array by stripping the high order bits from
-     * each character. Use {@link #getBytes()} or {@link #getBytes(String)} instead.
-     *
-     * @param start
-     *            the starting offset of characters to copy.
-     * @param end
-     *            the ending offset of characters to copy.
-     * @param data
-     *            the destination byte array.
-     * @param index
-     *            the starting offset in the destination byte array.
-     * @throws NullPointerException
-     *             if {@code data} is {@code null}.
-     * @throws IndexOutOfBoundsException
-     *             if {@code start < 0}, {@code end > length()}, {@code index <
-     *             0} or {@code end - start > data.length - index}.
-     * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)} instead.
-     */
-    @Deprecated
-    public void getBytes(int start, int end, byte[] data, int index) {
-        // Note: last character not copied!
-        if (start >= 0 && start <= end && end <= count) {
-            end += offset;
-            try {
-                for (int i = offset + start; i < end; i++) {
-                    data[index++] = (byte) value[i];
-                }
-            } catch (ArrayIndexOutOfBoundsException ignored) {
-                throw failedBoundsCheck(data.length, index, end - start);
-            }
-        } else {
-            throw startEndAndLength(start, end);
-        }
-    }
-
-    /**
-     * Returns a new byte array containing the characters of this string encoded using the
-     * system's {@link java.nio.charset.Charset#defaultCharset default charset}.
-     *
-     * <p>The behavior when this string cannot be represented in the system's default charset
-     * is unspecified. In practice, when the default charset is UTF-8 (as it is on Android),
-     * all strings can be encoded.
-     */
-    public byte[] getBytes() {
-        return getBytes(Charset.defaultCharset());
-    }
-
-    /**
-     * Returns a new byte array containing the characters of this string encoded using the
-     * named charset.
-     *
-     * <p>The behavior when this string cannot be represented in the named charset
-     * is unspecified. Use {@link java.nio.charset.CharsetEncoder} for more control.
-     *
-     * @throws UnsupportedEncodingException if the charset is not supported
-     */
-    public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
-        return getBytes(Charset.forNameUEE(charsetName));
-    }
-
-    /**
-     * Returns a new byte array containing the characters of this string encoded using the
-     * given charset.
-     *
-     * <p>The behavior when this string cannot be represented in the given charset
-     * is to replace malformed input and unmappable characters with the charset's default
-     * replacement byte array. Use {@link java.nio.charset.CharsetEncoder} for more control.
-     *
-     * @since 1.6
-     */
-    public byte[] getBytes(Charset charset) {
-        String canonicalCharsetName = charset.name();
-        if (canonicalCharsetName.equals("UTF-8")) {
-            return Charsets.toUtf8Bytes(value, offset, count);
-        } else if (canonicalCharsetName.equals("ISO-8859-1")) {
-            return Charsets.toIsoLatin1Bytes(value, offset, count);
-        } else if (canonicalCharsetName.equals("US-ASCII")) {
-            return Charsets.toAsciiBytes(value, offset, count);
-        } else if (canonicalCharsetName.equals("UTF-16BE")) {
-            return Charsets.toBigEndianUtf16Bytes(value, offset, count);
-        } else {
-            CharBuffer chars = CharBuffer.wrap(this.value, this.offset, this.count);
-            ByteBuffer buffer = charset.encode(chars.asReadOnlyBuffer());
-            byte[] bytes = new byte[buffer.limit()];
-            buffer.get(bytes);
-            return bytes;
-        }
-    }
-
-    /**
-     * Copies the specified characters in this string to the character array
-     * starting at the specified offset in the character array.
-     *
-     * @param start
-     *            the starting offset of characters to copy.
-     * @param end
-     *            the ending offset of characters to copy.
-     * @param buffer
-     *            the destination character array.
-     * @param index
-     *            the starting offset in the character array.
-     * @throws NullPointerException
-     *             if {@code buffer} is {@code null}.
-     * @throws IndexOutOfBoundsException
-     *             if {@code start < 0}, {@code end > length()}, {@code start >
-     *             end}, {@code index < 0}, {@code end - start > buffer.length -
-     *             index}
-     */
-    public void getChars(int start, int end, char[] buffer, int index) {
-        // Note: last character not copied!
-        if (start >= 0 && start <= end && end <= count) {
-            System.arraycopy(value, start + offset, buffer, index, end - start);
-        } else {
-            // We throw StringIndexOutOfBoundsException rather than System.arraycopy's AIOOBE.
-            throw startEndAndLength(start, end);
-        }
-    }
-
-    /**
-     * Version of getChars without bounds checks, for use by other classes
-     * within the java.lang package only.  The caller is responsible for
-     * ensuring that start >= 0 && start <= end && end <= count.
-     */
-    void _getChars(int start, int end, char[] buffer, int index) {
-        // NOTE last character not copied!
-        System.arraycopy(value, start + offset, buffer, index, end - start);
-    }
-
-    @Override public int hashCode() {
-        int hash = hashCode;
-        if (hash == 0) {
-            if (count == 0) {
-                return 0;
-            }
-            final int end = count + offset;
-            final char[] chars = value;
-            for (int i = offset; i < end; ++i) {
-                hash = 31*hash + chars[i];
-            }
-            hashCode = hash;
-        }
-        return hash;
-    }
-
-    /**
-     * Searches in this string for the first index of the specified character.
-     * The search for the character starts at the beginning and moves towards
-     * the end of this string.
-     *
-     * @param c
-     *            the character to find.
-     * @return the index in this string of the specified character, -1 if the
-     *         character isn't found.
-     */
-    public int indexOf(int c) {
-        // TODO: just "return indexOf(c, 0);" when the JIT can inline that deep.
-        if (c > 0xffff) {
-            return indexOfSupplementary(c, 0);
-        }
-        return fastIndexOf(c, 0);
-    }
-
-    /**
-     * Searches in this string for the index of the specified character. The
-     * search for the character starts at the specified offset and moves towards
-     * the end of this string.
-     *
-     * @param c
-     *            the character to find.
-     * @param start
-     *            the starting offset.
-     * @return the index in this string of the specified character, -1 if the
-     *         character isn't found.
-     */
-    public int indexOf(int c, int start) {
-        if (c > 0xffff) {
-            return indexOfSupplementary(c, start);
-        }
-        return fastIndexOf(c, start);
-    }
-
-    private native int fastIndexOf(int c, int start);
-
-    private int indexOfSupplementary(int c, int start) {
-        if (!Character.isSupplementaryCodePoint(c)) {
-            return -1;
-        }
-        char[] chars = Character.toChars(c);
-        String needle = new String(0, chars.length, chars);
-        return indexOf(needle, start);
-    }
-
-    /**
-     * Searches in this string for the first index of the specified string. The
-     * search for the string starts at the beginning and moves towards the end
-     * of this string.
-     *
-     * @param string
-     *            the string to find.
-     * @return the index of the first character of the specified string in this
-     *         string, -1 if the specified string is not a substring.
-     * @throws NullPointerException
-     *             if {@code string} is {@code null}.
-     */
-    public int indexOf(String string) {
-        int start = 0;
-        int subCount = string.count;
-        int _count = count;
-        if (subCount > 0) {
-            if (subCount > _count) {
-                return -1;
-            }
-            char[] target = string.value;
-            int subOffset = string.offset;
-            char firstChar = target[subOffset];
-            int end = subOffset + subCount;
-            while (true) {
-                int i = indexOf(firstChar, start);
-                if (i == -1 || subCount + i > _count) {
-                    return -1; // handles subCount > count || start >= count
-                }
-                int o1 = offset + i, o2 = subOffset;
-                char[] _value = value;
-                while (++o2 < end && _value[++o1] == target[o2]) {
-                    // Intentionally empty
-                }
-                if (o2 == end) {
-                    return i;
-                }
-                start = i + 1;
-            }
-        }
-        return start < _count ? start : _count;
-    }
-
-    /**
-     * Searches in this string for the index of the specified string. The search
-     * for the string starts at the specified offset and moves towards the end
-     * of this string.
-     *
-     * @param subString
-     *            the string to find.
-     * @param start
-     *            the starting offset.
-     * @return the index of the first character of the specified string in this
-     *         string, -1 if the specified string is not a substring.
-     * @throws NullPointerException
-     *             if {@code subString} is {@code null}.
-     */
-    public int indexOf(String subString, int start) {
-        if (start < 0) {
-            start = 0;
-        }
-        int subCount = subString.count;
-        int _count = count;
-        if (subCount > 0) {
-            if (subCount + start > _count) {
-                return -1;
-            }
-            char[] target = subString.value;
-            int subOffset = subString.offset;
-            char firstChar = target[subOffset];
-            int end = subOffset + subCount;
-            while (true) {
-                int i = indexOf(firstChar, start);
-                if (i == -1 || subCount + i > _count) {
-                    return -1; // handles subCount > count || start >= count
-                }
-                int o1 = offset + i, o2 = subOffset;
-                char[] _value = value;
-                while (++o2 < end && _value[++o1] == target[o2]) {
-                    // Intentionally empty
-                }
-                if (o2 == end) {
-                    return i;
-                }
-                start = i + 1;
-            }
-        }
-        return start < _count ? start : _count;
-    }
-
-    /**
-     * Returns an interned string equal to this string. The VM maintains an internal set of
-     * unique strings. All string literals found in loaded classes'
-     * constant pools are automatically interned. Manually-interned strings are only weakly
-     * referenced, so calling {@code intern} won't lead to unwanted retention.
-     *
-     * <p>Interning is typically used because it guarantees that for interned strings
-     * {@code a} and {@code b}, {@code a.equals(b)} can be simplified to
-     * {@code a == b}. (This is not true of non-interned strings.)
-     *
-     * <p>Many applications find it simpler and more convenient to use an explicit
-     * {@link java.util.HashMap} to implement their own pools.
-     */
-    public native String intern();
-
-    /**
-     * Returns true if the length of this string is 0.
-     *
-     * @since 1.6
-     */
-    public boolean isEmpty() {
-        return count == 0;
-    }
-
-    /**
-     * Returns the last index of the code point {@code c}, or -1.
-     * The search for the character starts at the end and moves towards the
-     * beginning of this string.
-     */
-    public int lastIndexOf(int c) {
-        if (c > 0xffff) {
-            return lastIndexOfSupplementary(c, Integer.MAX_VALUE);
-        }
-        int _count = count;
-        int _offset = offset;
-        char[] _value = value;
-        for (int i = _offset + _count - 1; i >= _offset; --i) {
-            if (_value[i] == c) {
-                return i - _offset;
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Returns the last index of the code point {@code c}, or -1.
-     * The search for the character starts at offset {@code start} and moves towards
-     * the beginning of this string.
-     */
-    public int lastIndexOf(int c, int start) {
-        if (c > 0xffff) {
-            return lastIndexOfSupplementary(c, start);
-        }
-        int _count = count;
-        int _offset = offset;
-        char[] _value = value;
-        if (start >= 0) {
-            if (start >= _count) {
-                start = _count - 1;
-            }
-            for (int i = _offset + start; i >= _offset; --i) {
-                if (_value[i] == c) {
-                    return i - _offset;
-                }
-            }
-        }
-        return -1;
-    }
-
-    private int lastIndexOfSupplementary(int c, int start) {
-        if (!Character.isSupplementaryCodePoint(c)) {
-            return -1;
-        }
-        char[] chars = Character.toChars(c);
-        String needle = new String(0, chars.length, chars);
-        return lastIndexOf(needle, start);
-    }
-
-    /**
-     * Searches in this string for the last index of the specified string. The
-     * search for the string starts at the end and moves towards the beginning
-     * of this string.
-     *
-     * @param string
-     *            the string to find.
-     * @return the index of the first character of the specified string in this
-     *         string, -1 if the specified string is not a substring.
-     * @throws NullPointerException
-     *             if {@code string} is {@code null}.
-     */
-    public int lastIndexOf(String string) {
-        // Use count instead of count - 1 so lastIndexOf("") returns count
-        return lastIndexOf(string, count);
-    }
-
-    /**
-     * Searches in this string for the index of the specified string. The search
-     * for the string starts at the specified offset and moves towards the
-     * beginning of this string.
-     *
-     * @param subString
-     *            the string to find.
-     * @param start
-     *            the starting offset.
-     * @return the index of the first character of the specified string in this
-     *         string , -1 if the specified string is not a substring.
-     * @throws NullPointerException
-     *             if {@code subString} is {@code null}.
-     */
-    public int lastIndexOf(String subString, int start) {
-        int subCount = subString.count;
-        if (subCount <= count && start >= 0) {
-            if (subCount > 0) {
-                if (start > count - subCount) {
-                    start = count - subCount;
-                }
-                // count and subCount are both >= 1
-                char[] target = subString.value;
-                int subOffset = subString.offset;
-                char firstChar = target[subOffset];
-                int end = subOffset + subCount;
-                while (true) {
-                    int i = lastIndexOf(firstChar, start);
-                    if (i == -1) {
-                        return -1;
-                    }
-                    int o1 = offset + i, o2 = subOffset;
-                    while (++o2 < end && value[++o1] == target[o2]) {
-                        // Intentionally empty
-                    }
-                    if (o2 == end) {
-                        return i;
-                    }
-                    start = i - 1;
-                }
-            }
-            return start < count ? start : count;
-        }
-        return -1;
-    }
-
-    /**
-     * Returns the number of characters in this string.
-     */
-    public int length() {
-        return count;
-    }
-
-    /**
-     * Compares the specified string to this string and compares the specified
-     * range of characters to determine if they are the same.
-     *
-     * @param thisStart
-     *            the starting offset in this string.
-     * @param string
-     *            the string to compare.
-     * @param start
-     *            the starting offset in the specified string.
-     * @param length
-     *            the number of characters to compare.
-     * @return {@code true} if the ranges of characters are equal, {@code false}
-     *         otherwise
-     * @throws NullPointerException
-     *             if {@code string} is {@code null}.
-     */
-    public boolean regionMatches(int thisStart, String string, int start, int length) {
-        if (string == null) {
-            throw new NullPointerException("string == null");
-        }
-        if (start < 0 || string.count - start < length) {
-            return false;
-        }
-        if (thisStart < 0 || count - thisStart < length) {
-            return false;
-        }
-        if (length <= 0) {
-            return true;
-        }
-        int o1 = offset + thisStart, o2 = string.offset + start;
-        char[] value1 = value;
-        char[] value2 = string.value;
-        for (int i = 0; i < length; ++i) {
-            if (value1[o1 + i] != value2[o2 + i]) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Compares the specified string to this string and compares the specified
-     * range of characters to determine if they are the same. When ignoreCase is
-     * true, the case of the characters is ignored during the comparison.
-     *
-     * @param ignoreCase
-     *            specifies if case should be ignored.
-     * @param thisStart
-     *            the starting offset in this string.
-     * @param string
-     *            the string to compare.
-     * @param start
-     *            the starting offset in the specified string.
-     * @param length
-     *            the number of characters to compare.
-     * @return {@code true} if the ranges of characters are equal, {@code false}
-     *         otherwise.
-     * @throws NullPointerException
-     *             if {@code string} is {@code null}.
-     */
-    public boolean regionMatches(boolean ignoreCase, int thisStart, String string, int start, int length) {
-        if (!ignoreCase) {
-            return regionMatches(thisStart, string, start, length);
-        }
-        if (string == null) {
-            throw new NullPointerException("string == null");
-        }
-        if (thisStart < 0 || length > count - thisStart) {
-            return false;
-        }
-        if (start < 0 || length > string.count - start) {
-            return false;
-        }
-        thisStart += offset;
-        start += string.offset;
-        int end = thisStart + length;
-        char[] target = string.value;
-        while (thisStart < end) {
-            char c1 = value[thisStart++];
-            char c2 = target[start++];
-            if (c1 != c2 && foldCase(c1) != foldCase(c2)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Copies this string replacing occurrences of the specified character with
-     * another character.
-     *
-     * @param oldChar
-     *            the character to replace.
-     * @param newChar
-     *            the replacement character.
-     * @return a new string with occurrences of oldChar replaced by newChar.
-     */
-    public String replace(char oldChar, char newChar) {
-        char[] buffer = value;
-        int _offset = offset;
-        int _count = count;
-
-        int idx = _offset;
-        int last = _offset + _count;
-        boolean copied = false;
-        while (idx < last) {
-            if (buffer[idx] == oldChar) {
-                if (!copied) {
-                    char[] newBuffer = new char[_count];
-                    System.arraycopy(buffer, _offset, newBuffer, 0, _count);
-                    buffer = newBuffer;
-                    idx -= _offset;
-                    last -= _offset;
-                    copied = true;
-                }
-                buffer[idx] = newChar;
-            }
-            idx++;
-        }
-
-        return copied ? new String(0, count, buffer) : this;
-    }
-
-    /**
-     * Copies this string replacing occurrences of the specified target sequence
-     * with another sequence. The string is processed from the beginning to the
-     * end.
-     *
-     * @param target
-     *            the sequence to replace.
-     * @param replacement
-     *            the replacement sequence.
-     * @return the resulting string.
-     * @throws NullPointerException
-     *             if {@code target} or {@code replacement} is {@code null}.
-     */
-    public String replace(CharSequence target, CharSequence replacement) {
-        if (target == null) {
-            throw new NullPointerException("target == null");
-        }
-        if (replacement == null) {
-            throw new NullPointerException("replacement == null");
-        }
-
-        String targetString = target.toString();
-        int matchStart = indexOf(targetString, 0);
-        if (matchStart == -1) {
-            // If there's nothing to replace, return the original string untouched.
-            return this;
-        }
-
-        String replacementString = replacement.toString();
-
-        // The empty target matches at the start and end and between each character.
-        int targetLength = targetString.length();
-        if (targetLength == 0) {
-            // The result contains the original 'count' characters, a copy of the
-            // replacement string before every one of those characters, and a final
-            // copy of the replacement string at the end.
-            int resultLength = count + (count + 1) * replacementString.length();
-            StringBuilder result = new StringBuilder(resultLength);
-            result.append(replacementString);
-            int end = offset + count;
-            for (int i = offset; i != end; ++i) {
-                result.append(value[i]);
-                result.append(replacementString);
-            }
-            return result.toString();
-        }
-
-        StringBuilder result = new StringBuilder(count);
-        int searchStart = 0;
-        do {
-            // Copy characters before the match...
-            result.append(value, offset + searchStart, matchStart - searchStart);
-            // Insert the replacement...
-            result.append(replacementString);
-            // And skip over the match...
-            searchStart = matchStart + targetLength;
-        } while ((matchStart = indexOf(targetString, searchStart)) != -1);
-        // Copy any trailing chars...
-        result.append(value, offset + searchStart, count - searchStart);
-        return result.toString();
-    }
-
-    /**
-     * Compares the specified string to this string to determine if the
-     * specified string is a prefix.
-     *
-     * @param prefix
-     *            the string to look for.
-     * @return {@code true} if the specified string is a prefix of this string,
-     *         {@code false} otherwise
-     * @throws NullPointerException
-     *             if {@code prefix} is {@code null}.
-     */
-    public boolean startsWith(String prefix) {
-        return startsWith(prefix, 0);
-    }
-
-    /**
-     * Compares the specified string to this string, starting at the specified
-     * offset, to determine if the specified string is a prefix.
-     *
-     * @param prefix
-     *            the string to look for.
-     * @param start
-     *            the starting offset.
-     * @return {@code true} if the specified string occurs in this string at the
-     *         specified offset, {@code false} otherwise.
-     * @throws NullPointerException
-     *             if {@code prefix} is {@code null}.
-     */
-    public boolean startsWith(String prefix, int start) {
-        return regionMatches(start, prefix, 0, prefix.count);
-    }
-
-    /**
-     * Returns a string containing a suffix of this string. The returned string
-     * shares this string's <a href="#backing_array">backing array</a>.
-     *
-     * @param start
-     *            the offset of the first character.
-     * @return a new string containing the characters from start to the end of
-     *         the string.
-     * @throws IndexOutOfBoundsException
-     *             if {@code start < 0} or {@code start > length()}.
-     */
-    public String substring(int start) {
-        if (start == 0) {
-            return this;
-        }
-        if (start >= 0 && start <= count) {
-            return new String(offset + start, count - start, value);
-        }
-        throw indexAndLength(start);
-    }
-
-    /**
-     * Returns a string containing a subsequence of characters from this string.
-     * The returned string shares this string's <a href="#backing_array">backing
-     * array</a>.
-     *
-     * @param start
-     *            the offset of the first character.
-     * @param end
-     *            the offset one past the last character.
-     * @return a new string containing the characters from start to end - 1
-     * @throws IndexOutOfBoundsException
-     *             if {@code start < 0}, {@code start > end} or {@code end >
-     *             length()}.
-     */
-    public String substring(int start, int end) {
-        if (start == 0 && end == count) {
-            return this;
-        }
-        // NOTE last character not copied!
-        // Fast range check.
-        if (start >= 0 && start <= end && end <= count) {
-            return new String(offset + start, end - start, value);
-        }
-        throw startEndAndLength(start, end);
-    }
-
-    /**
-     * Returns a new {@code char} array containing a copy of the characters in this string.
-     * This is expensive and rarely useful. If you just want to iterate over the characters in
-     * the string, use {@link #charAt} instead.
-     */
-    public char[] toCharArray() {
-        char[] buffer = new char[count];
-        System.arraycopy(value, offset, buffer, 0, count);
-        return buffer;
-    }
-
-    /**
-     * Converts this string to lower case, using the rules of the user's default locale.
-     * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
-     *
-     * @return a new lower case string, or {@code this} if it's already all lower case.
-     */
-    public String toLowerCase() {
-        return CaseMapper.toLowerCase(Locale.getDefault(), this, value, offset, count);
-    }
-
-    /**
-     * Converts this string to lower case, using the rules of {@code locale}.
-     *
-     * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include
-     * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in
-     * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get
-     * correct case mapping of Greek characters: any locale will do.
-     *
-     * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a>
-     * for full details of context- and language-specific special cases.
-     *
-     * @return a new lower case string, or {@code this} if it's already all lower case.
-     */
-    public String toLowerCase(Locale locale) {
-        return CaseMapper.toLowerCase(locale, this, value, offset, count);
-    }
-
-    /**
-     * Returns this string.
-     */
-    @Override
-    public String toString() {
-        return this;
-    }
-
-    /**
-     * Converts this this string to upper case, using the rules of the user's default locale.
-     * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
-     *
-     * @return a new upper case string, or {@code this} if it's already all upper case.
-     */
-    public String toUpperCase() {
-        return CaseMapper.toUpperCase(Locale.getDefault(), this, value, offset, count);
-    }
-
-    /**
-     * Converts this this string to upper case, using the rules of {@code locale}.
-     *
-     * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include
-     * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in
-     * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get
-     * correct case mapping of Greek characters: any locale will do.
-     *
-     * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a>
-     * for full details of context- and language-specific special cases.
-     *
-     * @return a new upper case string, or {@code this} if it's already all upper case.
-     */
-    public String toUpperCase(Locale locale) {
-        return CaseMapper.toUpperCase(locale, this, value, offset, count);
-    }
-
-    /**
-     * Copies this string removing white space characters from the beginning and
-     * end of the string.
-     *
-     * @return a new string with characters <code><= \\u0020</code> removed from
-     *         the beginning and the end.
-     */
-    public String trim() {
-        int start = offset, last = offset + count - 1;
-        int end = last;
-        while ((start <= end) && (value[start] <= ' ')) {
-            start++;
-        }
-        while ((end >= start) && (value[end] <= ' ')) {
-            end--;
-        }
-        if (start == offset && end == last) {
-            return this;
-        }
-        return new String(start, end - start + 1, value);
-    }
-
-    /**
-     * Creates a new string containing the characters in the specified character
-     * array. Modifying the character array after creating the string has no
-     * effect on the string.
-     *
-     * @param data
-     *            the array of characters.
-     * @return the new string.
-     * @throws NullPointerException
-     *             if {@code data} is {@code null}.
-     */
-    public static String valueOf(char[] data) {
-        return new String(data, 0, data.length);
-    }
-
-    /**
-     * Creates a new string containing the specified characters in the character
-     * array. Modifying the character array after creating the string has no
-     * effect on the string.
-     *
-     * @param data
-     *            the array of characters.
-     * @param start
-     *            the starting offset in the character array.
-     * @param length
-     *            the number of characters to use.
-     * @return the new string.
-     * @throws IndexOutOfBoundsException
-     *             if {@code length < 0}, {@code start < 0} or {@code start +
-     *             length > data.length}
-     * @throws NullPointerException
-     *             if {@code data} is {@code null}.
-     */
-    public static String valueOf(char[] data, int start, int length) {
-        return new String(data, start, length);
-    }
-
-    /**
-     * Converts the specified character to its string representation.
-     *
-     * @param value
-     *            the character.
-     * @return the character converted to a string.
-     */
-    public static String valueOf(char value) {
-        String s;
-        if (value < 128) {
-            s = new String(value, 1, ASCII);
-        } else {
-            s = new String(0, 1, new char[] { value });
-        }
-        s.hashCode = value;
-        return s;
-    }
-
-    /**
-     * Converts the specified double to its string representation.
-     *
-     * @param value
-     *            the double.
-     * @return the double converted to a string.
-     */
-    public static String valueOf(double value) {
-        return Double.toString(value);
-    }
-
-    /**
-     * Converts the specified float to its string representation.
-     *
-     * @param value
-     *            the float.
-     * @return the float converted to a string.
-     */
-    public static String valueOf(float value) {
-        return Float.toString(value);
-    }
-
-    /**
-     * Converts the specified integer to its string representation.
-     *
-     * @param value
-     *            the integer.
-     * @return the integer converted to a string.
-     */
-    public static String valueOf(int value) {
-        return Integer.toString(value);
-    }
-
-    /**
-     * Converts the specified long to its string representation.
-     *
-     * @param value
-     *            the long.
-     * @return the long converted to a string.
-     */
-    public static String valueOf(long value) {
-        return Long.toString(value);
-    }
-
-    /**
-     * Converts the specified object to its string representation. If the object
-     * is null return the string {@code "null"}, otherwise use {@code
-     * toString()} to get the string representation.
-     *
-     * @param value
-     *            the object.
-     * @return the object converted to a string, or the string {@code "null"}.
-     */
-    public static String valueOf(Object value) {
-        return value != null ? value.toString() : "null";
-    }
-
-    /**
-     * Converts the specified boolean to its string representation. When the
-     * boolean is {@code true} return {@code "true"}, otherwise return {@code
-     * "false"}.
-     *
-     * @param value
-     *            the boolean.
-     * @return the boolean converted to a string.
-     */
-    public static String valueOf(boolean value) {
-        return value ? "true" : "false";
-    }
-
-    /**
-     * Returns whether the characters in the StringBuffer {@code strbuf} are the
-     * same as those in this string.
-     *
-     * @param strbuf
-     *            the StringBuffer to compare this string to.
-     * @return {@code true} if the characters in {@code strbuf} are identical to
-     *         those in this string. If they are not, {@code false} will be
-     *         returned.
-     * @throws NullPointerException
-     *             if {@code strbuf} is {@code null}.
-     * @since 1.4
-     */
-    public boolean contentEquals(StringBuffer strbuf) {
-        synchronized (strbuf) {
-            int size = strbuf.length();
-            if (count != size) {
-                return false;
-            }
-            return regionMatches(0, new String(0, size, strbuf.getValue()), 0,
-                    size);
-        }
-    }
-
-    /**
-     * Compares a {@code CharSequence} to this {@code String} to determine if
-     * their contents are equal.
-     *
-     * @param cs
-     *            the character sequence to compare to.
-     * @return {@code true} if equal, otherwise {@code false}
-     * @since 1.5
-     */
-    public boolean contentEquals(CharSequence cs) {
-        if (cs == null) {
-            throw new NullPointerException("cs == null");
-        }
-
-        int len = cs.length();
-
-        if (len != count) {
-            return false;
-        }
-
-        if (len == 0 && count == 0) {
-            return true; // since both are empty strings
-        }
-
-        return regionMatches(0, cs.toString(), 0, len);
-    }
-
-    /**
-     * Tests whether this string matches the given {@code regularExpression}. This method returns
-     * true only if the regular expression matches the <i>entire</i> input string. A common mistake is
-     * to assume that this method behaves like {@link #contains}; if you want to match anywhere
-     * within the input string, you need to add {@code .*} to the beginning and end of your
-     * regular expression. See {@link Pattern#matches}.
-     *
-     * <p>If the same regular expression is to be used for multiple operations, it may be more
-     * efficient to reuse a compiled {@code Pattern}.
-     *
-     * @throws PatternSyntaxException
-     *             if the syntax of the supplied regular expression is not
-     *             valid.
-     * @throws NullPointerException if {@code regularExpression == null}
-     * @since 1.4
-     */
-    public boolean matches(String regularExpression) {
-        return Pattern.matches(regularExpression, this);
-    }
-
-    /**
-     * Replaces all matches for {@code regularExpression} within this string with the given
-     * {@code replacement}.
-     * See {@link Pattern} for regular expression syntax.
-     *
-     * <p>If the same regular expression is to be used for multiple operations, it may be more
-     * efficient to reuse a compiled {@code Pattern}.
-     *
-     * @throws PatternSyntaxException
-     *             if the syntax of the supplied regular expression is not
-     *             valid.
-     * @throws NullPointerException if {@code regularExpression == null}
-     * @see Pattern
-     * @since 1.4
-     */
-    public String replaceAll(String regularExpression, String replacement) {
-        return Pattern.compile(regularExpression).matcher(this).replaceAll(replacement);
-    }
-
-    /**
-     * Replaces the first match for {@code regularExpression} within this string with the given
-     * {@code replacement}.
-     * See {@link Pattern} for regular expression syntax.
-     *
-     * <p>If the same regular expression is to be used for multiple operations, it may be more
-     * efficient to reuse a compiled {@code Pattern}.
-     *
-     * @throws PatternSyntaxException
-     *             if the syntax of the supplied regular expression is not
-     *             valid.
-     * @throws NullPointerException if {@code regularExpression == null}
-     * @see Pattern
-     * @since 1.4
-     */
-    public String replaceFirst(String regularExpression, String replacement) {
-        return Pattern.compile(regularExpression).matcher(this).replaceFirst(replacement);
-    }
-
-    /**
-     * Splits this string using the supplied {@code regularExpression}.
-     * Equivalent to {@code split(regularExpression, 0)}.
-     * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}.
-     * See {@link Pattern} for regular expression syntax.
-     *
-     * <p>If the same regular expression is to be used for multiple operations, it may be more
-     * efficient to reuse a compiled {@code Pattern}.
-     *
-     * @throws NullPointerException if {@code regularExpression ==  null}
-     * @throws PatternSyntaxException
-     *             if the syntax of the supplied regular expression is not
-     *             valid.
-     * @see Pattern
-     * @since 1.4
-     */
-    public String[] split(String regularExpression) {
-        return split(regularExpression, 0);
-    }
-
-    /**
-     * Splits this string using the supplied {@code regularExpression}.
-     * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}.
-     * See {@link Pattern} for regular expression syntax.
-     *
-     * <p>If the same regular expression is to be used for multiple operations, it may be more
-     * efficient to reuse a compiled {@code Pattern}.
-     *
-     * @throws NullPointerException if {@code regularExpression ==  null}
-     * @throws PatternSyntaxException
-     *             if the syntax of the supplied regular expression is not
-     *             valid.
-     * @since 1.4
-     */
-    public String[] split(String regularExpression, int limit) {
-        String[] result = java.util.regex.Splitter.fastSplit(regularExpression, this, limit);
-        return result != null ? result : Pattern.compile(regularExpression).split(this, limit);
-    }
-
-    /**
-     * Has the same result as the substring function, but is present so that
-     * string may implement the CharSequence interface.
-     *
-     * @param start
-     *            the offset the first character.
-     * @param end
-     *            the offset of one past the last character to include.
-     * @return the subsequence requested.
-     * @throws IndexOutOfBoundsException
-     *             if {@code start < 0}, {@code end < 0}, {@code start > end} or
-     *             {@code end > length()}.
-     * @see java.lang.CharSequence#subSequence(int, int)
-     * @since 1.4
-     */
-    public CharSequence subSequence(int start, int end) {
-        return substring(start, end);
-    }
-
-    /**
-     * Returns the Unicode code point at the given {@code index}.
-     *
-     * @throws IndexOutOfBoundsException if {@code index < 0 || index >= length()}
-     * @see Character#codePointAt(char[], int, int)
-     * @since 1.5
-     */
-    public int codePointAt(int index) {
-        if (index < 0 || index >= count) {
-            throw indexAndLength(index);
-        }
-        return Character.codePointAt(value, offset + index, offset + count);
-    }
-
-    /**
-     * Returns the Unicode code point that precedes the given {@code index}.
-     *
-     * @throws IndexOutOfBoundsException if {@code index < 1 || index > length()}
-     * @see Character#codePointBefore(char[], int, int)
-     * @since 1.5
-     */
-    public int codePointBefore(int index) {
-        if (index < 1 || index > count) {
-            throw indexAndLength(index);
-        }
-        return Character.codePointBefore(value, offset + index, offset);
-    }
-
-    /**
-     * Calculates the number of Unicode code points between {@code start}
-     * and {@code end}.
-     *
-     * @param start
-     *            the inclusive beginning index of the subsequence.
-     * @param end
-     *            the exclusive end index of the subsequence.
-     * @return the number of Unicode code points in the subsequence.
-     * @throws IndexOutOfBoundsException
-     *         if {@code start < 0 || end > length() || start > end}
-     * @see Character#codePointCount(CharSequence, int, int)
-     * @since 1.5
-     */
-    public int codePointCount(int start, int end) {
-        if (start < 0 || end > count || start > end) {
-            throw startEndAndLength(start, end);
-        }
-        return Character.codePointCount(value, offset + start, end - start);
-    }
-
-    /**
-     * Determines if this {@code String} contains the sequence of characters in
-     * the {@code CharSequence} passed.
-     *
-     * @param cs
-     *            the character sequence to search for.
-     * @return {@code true} if the sequence of characters are contained in this
-     *         string, otherwise {@code false}.
-     * @since 1.5
-     */
-    public boolean contains(CharSequence cs) {
-        if (cs == null) {
-            throw new NullPointerException("cs == null");
-        }
-        return indexOf(cs.toString()) >= 0;
-    }
-
-    /**
-     * Returns the index within this object that is offset from {@code index} by
-     * {@code codePointOffset} code points.
-     *
-     * @param index
-     *            the index within this object to calculate the offset from.
-     * @param codePointOffset
-     *            the number of code points to count.
-     * @return the index within this object that is the offset.
-     * @throws IndexOutOfBoundsException
-     *             if {@code index} is negative or greater than {@code length()}
-     *             or if there aren't enough code points before or after {@code
-     *             index} to match {@code codePointOffset}.
-     * @since 1.5
-     */
-    public int offsetByCodePoints(int index, int codePointOffset) {
-        int s = index + offset;
-        int r = Character.offsetByCodePoints(value, offset, count, s, codePointOffset);
-        return r - offset;
-    }
-
-    /**
-     * Returns a localized formatted string, using the supplied format and arguments,
-     * using the user's default locale.
-     *
-     * <p>If you're formatting a string other than for human
-     * consumption, you should use the {@code format(Locale, String, Object...)}
-     * overload and supply {@code Locale.US}. See
-     * "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
-     *
-     * @param format the format string (see {@link java.util.Formatter#format})
-     * @param args
-     *            the list of arguments passed to the formatter. If there are
-     *            more arguments than required by {@code format},
-     *            additional arguments are ignored.
-     * @return the formatted string.
-     * @throws NullPointerException if {@code format == null}
-     * @throws java.util.IllegalFormatException
-     *             if the format is invalid.
-     * @since 1.5
-     */
-    public static String format(String format, Object... args) {
-        return format(Locale.getDefault(), format, args);
-    }
-
-    /**
-     * Returns a formatted string, using the supplied format and arguments,
-     * localized to the given locale.
-     *
-     * @param locale
-     *            the locale to apply; {@code null} value means no localization.
-     * @param format the format string (see {@link java.util.Formatter#format})
-     * @param args
-     *            the list of arguments passed to the formatter. If there are
-     *            more arguments than required by {@code format},
-     *            additional arguments are ignored.
-     * @return the formatted string.
-     * @throws NullPointerException if {@code format == null}
-     * @throws java.util.IllegalFormatException
-     *             if the format is invalid.
-     * @since 1.5
-     */
-    public static String format(Locale locale, String format, Object... args) {
-        if (format == null) {
-            throw new NullPointerException("format == null");
-        }
-        int bufferSize = format.length() + (args == null ? 0 : args.length * 10);
-        Formatter f = new Formatter(new StringBuilder(bufferSize), locale);
-        return f.format(format, args).toString();
-    }
-
-    /*
-     * An implementation of a String.indexOf that is supposed to perform
-     * substantially better than the default algorithm if the "needle" (the
-     * subString being searched for) is a constant string.
-     *
-     * For example, a JIT, upon encountering a call to String.indexOf(String),
-     * where the needle is a constant string, may compute the values cache, md2
-     * and lastChar, and change the call to the following method.
-     */
-    @FindBugsSuppressWarnings("UPM_UNCALLED_PRIVATE_METHOD")
-    @SuppressWarnings("unused")
-    private static int indexOf(String haystackString, String needleString,
-            int cache, int md2, char lastChar) {
-        char[] haystack = haystackString.value;
-        int haystackOffset = haystackString.offset;
-        int haystackLength = haystackString.count;
-        char[] needle = needleString.value;
-        int needleOffset = needleString.offset;
-        int needleLength = needleString.count;
-        int needleLengthMinus1 = needleLength - 1;
-        int haystackEnd = haystackOffset + haystackLength;
-        outer_loop: for (int i = haystackOffset + needleLengthMinus1; i < haystackEnd;) {
-            if (lastChar == haystack[i]) {
-                for (int j = 0; j < needleLengthMinus1; ++j) {
-                    if (needle[j + needleOffset] != haystack[i + j
-                            - needleLengthMinus1]) {
-                        int skip = 1;
-                        if ((cache & (1 << haystack[i])) == 0) {
-                            skip += j;
-                        }
-                        i += Math.max(md2, skip);
-                        continue outer_loop;
-                    }
-                }
-                return i - needleLengthMinus1 - haystackOffset;
-            }
-
-            if ((cache & (1 << haystack[i])) == 0) {
-                i += needleLengthMinus1;
-            }
-            i++;
-        }
-        return -1;
-    }
-}
diff --git a/libdvm/src/main/java/java/lang/Thread.java b/libdvm/src/main/java/java/lang/Thread.java
deleted file mode 100644
index a40dde1..0000000
--- a/libdvm/src/main/java/java/lang/Thread.java
+++ /dev/null
@@ -1,1288 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import dalvik.system.VMStack;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import libcore.util.EmptyArray;
-
-/**
- * A {@code Thread} is a concurrent unit of execution. It has its own call stack
- * for methods being invoked, their arguments and local variables. Each application
- * has at least one thread running when it is started, the main thread, in the main
- * {@link ThreadGroup}. The runtime keeps its own threads in the system thread
- * group.
- *
- * <p>There are two ways to execute code in a new thread.
- * You can either subclass {@code Thread} and overriding its {@link #run()} method,
- * or construct a new {@code Thread} and pass a {@link Runnable} to the constructor.
- * In either case, the {@link #start()} method must be called to actually execute
- * the new {@code Thread}.
- *
- * <p>Each {@code Thread} has an integer priority that affect how the thread is
- * scheduled by the OS. A new thread inherits the priority of its parent.
- * A thread's priority can be set using the {@link #setPriority(int)} method.
- */
-public class Thread implements Runnable {
-    private static final int NANOS_PER_MILLI = 1000000;
-
-    /** Park states */
-    private static class ParkState {
-        /** park state indicating unparked */
-        private static final int UNPARKED = 1;
-
-        /** park state indicating preemptively unparked */
-        private static final int PREEMPTIVELY_UNPARKED = 2;
-
-        /** park state indicating parked */
-        private static final int PARKED = 3;
-    }
-
-    /**
-     * A representation of a thread's state. A given thread may only be in one
-     * state at a time.
-     */
-    public enum State {
-        /**
-         * The thread has been created, but has never been started.
-         */
-        NEW,
-        /**
-         * The thread may be run.
-         */
-        RUNNABLE,
-        /**
-         * The thread is blocked and waiting for a lock.
-         */
-        BLOCKED,
-        /**
-         * The thread is waiting.
-         */
-        WAITING,
-        /**
-         * The thread is waiting for a specified amount of time.
-         */
-        TIMED_WAITING,
-        /**
-         * The thread has been terminated.
-         */
-        TERMINATED
-    }
-
-    /**
-     * The maximum priority value allowed for a thread.
-     * This corresponds to (but does not have the same value as)
-     * {@code android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY}.
-     */
-    public static final int MAX_PRIORITY = 10;
-
-    /**
-     * The minimum priority value allowed for a thread.
-     * This corresponds to (but does not have the same value as)
-     * {@code android.os.Process.THREAD_PRIORITY_LOWEST}.
-     */
-    public static final int MIN_PRIORITY = 1;
-
-    /**
-     * The normal (default) priority value assigned to the main thread.
-     * This corresponds to (but does not have the same value as)
-     * {@code android.os.Process.THREAD_PRIORITY_DEFAULT}.
-
-     */
-    public static final int NORM_PRIORITY = 5;
-
-    /* some of these are accessed directly by the VM; do not rename them */
-    volatile VMThread vmThread;
-    volatile ThreadGroup group;
-    volatile boolean daemon;
-    volatile String name;
-    volatile int priority;
-    volatile long stackSize;
-    Runnable target;
-    private static int count = 0;
-
-    /**
-     * Holds the thread's ID. We simply count upwards, so
-     * each Thread has a unique ID.
-     */
-    private long id;
-
-    /**
-     * Normal thread local values.
-     */
-    ThreadLocal.Values localValues;
-
-    /**
-     * Inheritable thread local values.
-     */
-    ThreadLocal.Values inheritableValues;
-
-    /** Callbacks to run on interruption. */
-    private final List<Runnable> interruptActions = new ArrayList<Runnable>();
-
-    /**
-     * Holds the class loader for this Thread, in case there is one.
-     */
-    private ClassLoader contextClassLoader;
-
-    /**
-     * Holds the handler for uncaught exceptions in this Thread,
-     * in case there is one.
-     */
-    private UncaughtExceptionHandler uncaughtHandler;
-
-    /**
-     * Holds the default handler for uncaught exceptions, in case there is one.
-     */
-    private static UncaughtExceptionHandler defaultUncaughtHandler;
-
-    /**
-     * Reflects whether this Thread has already been started. A Thread
-     * can only be started once (no recycling). Also, we need it to deduce
-     * the proper Thread status.
-     */
-    boolean hasBeenStarted = false;
-
-    /** the park state of the thread */
-    private int parkState = ParkState.UNPARKED;
-
-    /** The synchronization object responsible for this thread parking. */
-    private Object parkBlocker;
-
-    /**
-     * Constructs a new {@code Thread} with no {@code Runnable} object and a
-     * newly generated name. The new {@code Thread} will belong to the same
-     * {@code ThreadGroup} as the {@code Thread} calling this constructor.
-     *
-     * @see java.lang.ThreadGroup
-     * @see java.lang.Runnable
-     */
-    public Thread() {
-        create(null, null, null, 0);
-    }
-
-    /**
-     * Constructs a new {@code Thread} with a {@code Runnable} object and a
-     * newly generated name. The new {@code Thread} will belong to the same
-     * {@code ThreadGroup} as the {@code Thread} calling this constructor.
-     *
-     * @param runnable
-     *            a {@code Runnable} whose method <code>run</code> will be
-     *            executed by the new {@code Thread}
-     *
-     * @see java.lang.ThreadGroup
-     * @see java.lang.Runnable
-     */
-    public Thread(Runnable runnable) {
-        create(null, runnable, null, 0);
-    }
-
-    /**
-     * Constructs a new {@code Thread} with a {@code Runnable} object and name
-     * provided. The new {@code Thread} will belong to the same {@code
-     * ThreadGroup} as the {@code Thread} calling this constructor.
-     *
-     * @param runnable
-     *            a {@code Runnable} whose method <code>run</code> will be
-     *            executed by the new {@code Thread}
-     * @param threadName
-     *            the name for the {@code Thread} being created
-     *
-     * @see java.lang.ThreadGroup
-     * @see java.lang.Runnable
-     */
-    public Thread(Runnable runnable, String threadName) {
-        if (threadName == null) {
-            throw new NullPointerException("threadName == null");
-        }
-
-        create(null, runnable, threadName, 0);
-    }
-
-    /**
-     * Constructs a new {@code Thread} with no {@code Runnable} object and the
-     * name provided. The new {@code Thread} will belong to the same {@code
-     * ThreadGroup} as the {@code Thread} calling this constructor.
-     *
-     * @param threadName
-     *            the name for the {@code Thread} being created
-     *
-     * @see java.lang.ThreadGroup
-     * @see java.lang.Runnable
-     *
-     */
-    public Thread(String threadName) {
-        if (threadName == null) {
-            throw new NullPointerException("threadName == null");
-        }
-
-        create(null, null, threadName, 0);
-    }
-
-    /**
-     * Constructs a new {@code Thread} with a {@code Runnable} object and a
-     * newly generated name. The new {@code Thread} will belong to the {@code
-     * ThreadGroup} passed as parameter.
-     *
-     * @param group
-     *            {@code ThreadGroup} to which the new {@code Thread} will
-     *            belong
-     * @param runnable
-     *            a {@code Runnable} whose method <code>run</code> will be
-     *            executed by the new {@code Thread}
-     * @throws IllegalThreadStateException
-     *             if <code>group.destroy()</code> has already been done
-     * @see java.lang.ThreadGroup
-     * @see java.lang.Runnable
-     */
-    public Thread(ThreadGroup group, Runnable runnable) {
-        create(group, runnable, null, 0);
-    }
-
-    /**
-     * Constructs a new {@code Thread} with a {@code Runnable} object, the given
-     * name and belonging to the {@code ThreadGroup} passed as parameter.
-     *
-     * @param group
-     *            ThreadGroup to which the new {@code Thread} will belong
-     * @param runnable
-     *            a {@code Runnable} whose method <code>run</code> will be
-     *            executed by the new {@code Thread}
-     * @param threadName
-     *            the name for the {@code Thread} being created
-     * @throws IllegalThreadStateException
-     *             if <code>group.destroy()</code> has already been done
-     * @see java.lang.ThreadGroup
-     * @see java.lang.Runnable
-     */
-    public Thread(ThreadGroup group, Runnable runnable, String threadName) {
-        if (threadName == null) {
-            throw new NullPointerException("threadName == null");
-        }
-
-        create(group, runnable, threadName, 0);
-    }
-
-    /**
-     * Constructs a new {@code Thread} with no {@code Runnable} object, the
-     * given name and belonging to the {@code ThreadGroup} passed as parameter.
-     *
-     * @param group
-     *            {@code ThreadGroup} to which the new {@code Thread} will belong
-     * @param threadName
-     *            the name for the {@code Thread} being created
-     * @throws IllegalThreadStateException
-     *             if <code>group.destroy()</code> has already been done
-     * @see java.lang.ThreadGroup
-     * @see java.lang.Runnable
-     */
-    public Thread(ThreadGroup group, String threadName) {
-        if (threadName == null) {
-            throw new NullPointerException("threadName == null");
-        }
-
-        create(group, null, threadName, 0);
-    }
-
-    /**
-     * Constructs a new {@code Thread} with a {@code Runnable} object, the given
-     * name and belonging to the {@code ThreadGroup} passed as parameter.
-     *
-     * @param group
-     *            {@code ThreadGroup} to which the new {@code Thread} will
-     *            belong
-     * @param runnable
-     *            a {@code Runnable} whose method <code>run</code> will be
-     *            executed by the new {@code Thread}
-     * @param threadName
-     *            the name for the {@code Thread} being created
-     * @param stackSize
-     *            a stack size for the new {@code Thread}. This has a highly
-     *            platform-dependent interpretation. It may even be ignored
-     *            completely.
-     * @throws IllegalThreadStateException
-     *             if <code>group.destroy()</code> has already been done
-     * @see java.lang.ThreadGroup
-     * @see java.lang.Runnable
-     */
-    public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
-        if (threadName == null) {
-            throw new NullPointerException("threadName == null");
-        }
-        create(group, runnable, threadName, stackSize);
-    }
-
-    /**
-     * Package-scope method invoked by Dalvik VM to create "internal"
-     * threads or attach threads created externally.
-     *
-     * Don't call Thread.currentThread(), since there may not be such
-     * a thing (e.g. for Main).
-     */
-    Thread(ThreadGroup group, String name, int priority, boolean daemon) {
-        synchronized (Thread.class) {
-            id = ++Thread.count;
-        }
-
-        if (name == null) {
-            this.name = "Thread-" + id;
-        } else {
-            this.name = name;
-        }
-
-        if (group == null) {
-            throw new InternalError("group not specified");
-        }
-
-        this.group = group;
-
-        this.target = null;
-        this.stackSize = 0;
-        this.priority = priority;
-        this.daemon = daemon;
-
-        /* add ourselves to our ThreadGroup of choice */
-        this.group.addThread(this);
-    }
-
-    /**
-     * Initializes a new, existing Thread object with a runnable object,
-     * the given name and belonging to the ThreadGroup passed as parameter.
-     * This is the method that the several public constructors delegate their
-     * work to.
-     *
-     * @param group ThreadGroup to which the new Thread will belong
-     * @param runnable a java.lang.Runnable whose method <code>run</code> will
-     *        be executed by the new Thread
-     * @param threadName Name for the Thread being created
-     * @param stackSize Platform dependent stack size
-     * @throws IllegalThreadStateException if <code>group.destroy()</code> has
-     *         already been done
-     * @see java.lang.ThreadGroup
-     * @see java.lang.Runnable
-     */
-    private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
-        Thread currentThread = Thread.currentThread();
-        if (group == null) {
-            group = currentThread.getThreadGroup();
-        }
-
-        if (group.isDestroyed()) {
-            throw new IllegalThreadStateException("Group already destroyed");
-        }
-
-        this.group = group;
-
-        synchronized (Thread.class) {
-            id = ++Thread.count;
-        }
-
-        if (threadName == null) {
-            this.name = "Thread-" + id;
-        } else {
-            this.name = threadName;
-        }
-
-        this.target = runnable;
-        this.stackSize = stackSize;
-
-        this.priority = currentThread.getPriority();
-
-        this.contextClassLoader = currentThread.contextClassLoader;
-
-        // Transfer over InheritableThreadLocals.
-        if (currentThread.inheritableValues != null) {
-            inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues);
-        }
-
-        // add ourselves to our ThreadGroup of choice
-        this.group.addThread(this);
-    }
-
-    /**
-     * Returns the number of active {@code Thread}s in the running {@code
-     * Thread}'s group and its subgroups.
-     *
-     * @return the number of {@code Thread}s
-     */
-    public static int activeCount() {
-        return currentThread().getThreadGroup().activeCount();
-    }
-
-    /**
-     * Does nothing.
-     */
-    public final void checkAccess() {
-    }
-
-    /**
-     * Returns the number of stack frames in this thread.
-     *
-     * @return Number of stack frames
-     * @deprecated The results of this call were never well defined. To make
-     *             things worse, it would depend on whether the Thread was
-     *             suspended or not, and suspend was deprecated too.
-     */
-    @Deprecated
-    public int countStackFrames() {
-        return getStackTrace().length;
-    }
-
-    /**
-     * Returns the Thread of the caller, that is, the current Thread.
-     *
-     * @return the current Thread.
-     */
-    public static Thread currentThread() {
-        return VMThread.currentThread();
-    }
-
-    /**
-     * Throws {@code UnsupportedOperationException}.
-     * @deprecated Not implemented.
-     */
-    @Deprecated
-    public void destroy() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Prints to the standard error stream a text representation of the current
-     * stack for this Thread.
-     *
-     * @see Throwable#printStackTrace()
-     */
-    public static void dumpStack() {
-        new Throwable("stack dump").printStackTrace();
-    }
-
-    /**
-     * Copies an array with all Threads which are in the same ThreadGroup as the
-     * receiver - and subgroups - into the array <code>threads</code> passed as
-     * parameter. If the array passed as parameter is too small no exception is
-     * thrown - the extra elements are simply not copied.
-     *
-     * @param threads
-     *            array into which the Threads will be copied
-     * @return How many Threads were copied over
-     */
-    public static int enumerate(Thread[] threads) {
-        Thread thread = Thread.currentThread();
-        return thread.getThreadGroup().enumerate(threads);
-    }
-
-    /**
-     * Returns a map of all the currently live threads to their stack traces.
-     */
-    public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
-        Map<Thread, StackTraceElement[]> map = new HashMap<Thread, StackTraceElement[]>();
-
-        // Find out how many live threads we have. Allocate a bit more
-        // space than needed, in case new ones are just being created.
-        int count = ThreadGroup.mSystem.activeCount();
-        Thread[] threads = new Thread[count + count / 2];
-
-        // Enumerate the threads and collect the stacktraces.
-        count = ThreadGroup.mSystem.enumerate(threads);
-        for (int i = 0; i < count; i++) {
-            map.put(threads[i], threads[i].getStackTrace());
-        }
-
-        return map;
-    }
-
-    /**
-     * Returns the context ClassLoader for this Thread.
-     *
-     * @return ClassLoader The context ClassLoader
-     * @see java.lang.ClassLoader
-     * @see #getContextClassLoader()
-     */
-    public ClassLoader getContextClassLoader() {
-        return contextClassLoader;
-    }
-
-    /**
-     * Returns the default exception handler that's executed when uncaught
-     * exception terminates a thread.
-     *
-     * @return an {@link UncaughtExceptionHandler} or <code>null</code> if
-     *         none exists.
-     */
-    public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
-        return defaultUncaughtHandler;
-    }
-
-    /**
-     * Returns the thread's identifier. The ID is a positive <code>long</code>
-     * generated on thread creation, is unique to the thread, and doesn't change
-     * during the lifetime of the thread; the ID may be reused after the thread
-     * has been terminated.
-     *
-     * @return the thread's ID.
-     */
-    public long getId() {
-        return id;
-    }
-
-    /**
-     * Returns the name of the Thread.
-     */
-    public final String getName() {
-        return name;
-    }
-
-    /**
-     * Returns the priority of the Thread.
-     */
-    public final int getPriority() {
-        return priority;
-    }
-
-    /**
-     * Returns an array of {@link StackTraceElement} representing the current thread's stack.
-     */
-    public StackTraceElement[] getStackTrace() {
-        StackTraceElement ste[] = VMStack.getThreadStackTrace(this);
-        return ste != null ? ste : EmptyArray.STACK_TRACE_ELEMENT;
-    }
-
-    /**
-     * Returns the current state of the Thread. This method is useful for
-     * monitoring purposes.
-     *
-     * @return a {@link State} value.
-     */
-    public State getState() {
-        // TODO This is ugly and should be implemented better.
-        VMThread vmt = this.vmThread;
-
-        // Make sure we have a valid reference to an object. If native code
-        // deletes the reference we won't run into a null reference later.
-        VMThread thread = vmThread;
-        if (thread != null) {
-            // If the Thread Object became invalid or was not yet started,
-            // getStatus() will return -1.
-            int state = thread.getStatus();
-            if(state != -1) {
-                return VMThread.STATE_MAP[state];
-            }
-        }
-        return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW;
-    }
-
-    /**
-     * Returns the ThreadGroup to which this Thread belongs.
-     *
-     * @return the Thread's ThreadGroup
-     */
-    public final ThreadGroup getThreadGroup() {
-        // TODO This should actually be done at native termination.
-        if (getState() == Thread.State.TERMINATED) {
-            return null;
-        } else {
-            return group;
-        }
-    }
-
-    /**
-     * Returns the thread's uncaught exception handler. If not explicitly set,
-     * then the ThreadGroup's handler is returned. If the thread is terminated,
-     * then <code>null</code> is returned.
-     *
-     * @return an {@link UncaughtExceptionHandler} instance or {@code null}.
-     */
-    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
-        if (uncaughtHandler != null)
-            return uncaughtHandler;
-        else
-            return group;           // ThreadGroup is instance of UEH
-    }
-
-    /**
-     * Posts an interrupt request to this {@code Thread}. The behavior depends on
-     * the state of this {@code Thread}:
-     * <ul>
-     * <li>
-     * {@code Thread}s blocked in one of {@code Object}'s {@code wait()} methods
-     * or one of {@code Thread}'s {@code join()} or {@code sleep()} methods will
-     * be woken up, their interrupt status will be cleared, and they receive an
-     * {@link InterruptedException}.
-     * <li>
-     * {@code Thread}s blocked in an I/O operation of an
-     * {@link java.nio.channels.InterruptibleChannel} will have their interrupt
-     * status set and receive an
-     * {@link java.nio.channels.ClosedByInterruptException}. Also, the channel
-     * will be closed.
-     * <li>
-     * {@code Thread}s blocked in a {@link java.nio.channels.Selector} will have
-     * their interrupt status set and return immediately. They don't receive an
-     * exception in this case.
-     * <ul>
-     *
-     * @see Thread#interrupted
-     * @see Thread#isInterrupted
-     */
-    public void interrupt() {
-        // Interrupt this thread before running actions so that other
-        // threads that observe the interrupt as a result of an action
-        // will see that this thread is in the interrupted state.
-        VMThread vmt = this.vmThread;
-        if (vmt != null) {
-            vmt.interrupt();
-        }
-
-        synchronized (interruptActions) {
-            for (int i = interruptActions.size() - 1; i >= 0; i--) {
-                interruptActions.get(i).run();
-            }
-        }
-    }
-
-    /**
-     * Returns a <code>boolean</code> indicating whether the current Thread (
-     * <code>currentThread()</code>) has a pending interrupt request (<code>
-     * true</code>) or not (<code>false</code>). It also has the side-effect of
-     * clearing the flag.
-     *
-     * @return a <code>boolean</code> indicating the interrupt status
-     * @see Thread#currentThread
-     * @see Thread#interrupt
-     * @see Thread#isInterrupted
-     */
-    public static boolean interrupted() {
-        return VMThread.interrupted();
-    }
-
-    /**
-     * Returns <code>true</code> if the receiver has already been started and
-     * still runs code (hasn't died yet). Returns <code>false</code> either if
-     * the receiver hasn't been started yet or if it has already started and run
-     * to completion and died.
-     *
-     * @return a <code>boolean</code> indicating the liveness of the Thread
-     * @see Thread#start
-     */
-    public final boolean isAlive() {
-        return (vmThread != null);
-    }
-
-    /**
-     * Tests whether this is a daemon thread.
-     * A daemon thread only runs as long as there are non-daemon threads running.
-     * When the last non-daemon thread ends, the runtime will exit. This is not
-     * normally relevant to applications with a UI.
-     */
-    public final boolean isDaemon() {
-        return daemon;
-    }
-
-    /**
-     * Returns a <code>boolean</code> indicating whether the receiver has a
-     * pending interrupt request (<code>true</code>) or not (
-     * <code>false</code>)
-     *
-     * @return a <code>boolean</code> indicating the interrupt status
-     * @see Thread#interrupt
-     * @see Thread#interrupted
-     */
-    public boolean isInterrupted() {
-        VMThread vmt = this.vmThread;
-        if (vmt != null) {
-            return vmt.isInterrupted();
-        }
-
-        return false;
-    }
-
-    /**
-     * Blocks the current Thread (<code>Thread.currentThread()</code>) until
-     * the receiver finishes its execution and dies.
-     *
-     * @throws InterruptedException if the current thread has been interrupted.
-     *         The interrupted status of the current thread will be cleared before the exception is
-     *         thrown.
-     * @see Object#notifyAll
-     * @see java.lang.ThreadDeath
-     */
-    public final void join() throws InterruptedException {
-        VMThread t = vmThread;
-        if (t == null) {
-            return;
-        }
-
-        synchronized (t) {
-            while (isAlive()) {
-                t.wait();
-            }
-        }
-    }
-
-    /**
-     * Blocks the current Thread (<code>Thread.currentThread()</code>) until
-     * the receiver finishes its execution and dies or the specified timeout
-     * expires, whatever happens first.
-     *
-     * <p>A timeout of zero means the calling thread should wait forever unless interrupted.
-     *
-     * @param millis The maximum time to wait (in milliseconds).
-     * @throws InterruptedException if the current thread has been interrupted.
-     *         The interrupted status of the current thread will be cleared before the exception is
-     *         thrown.
-     * @see Object#notifyAll
-     * @see java.lang.ThreadDeath
-     */
-    public final void join(long millis) throws InterruptedException {
-        join(millis, 0);
-    }
-
-    /**
-     * Blocks the current Thread (<code>Thread.currentThread()</code>) until
-     * the receiver finishes its execution and dies or the specified timeout
-     * expires, whatever happens first.
-     *
-     * <p>A timeout of zero means the calling thread should wait forever unless interrupted.
-     *
-     * @param millis The maximum time to wait (in milliseconds).
-     * @param nanos Extra nanosecond precision
-     * @throws InterruptedException if the current thread has been interrupted.
-     *         The interrupted status of the current thread will be cleared before the exception is
-     *         thrown.
-     * @see Object#notifyAll
-     * @see java.lang.ThreadDeath
-     */
-    public final void join(long millis, int nanos) throws InterruptedException {
-        if (millis < 0 || nanos < 0 || nanos >= NANOS_PER_MILLI) {
-            throw new IllegalArgumentException("bad timeout: millis=" + millis + ",nanos=" + nanos);
-        }
-
-        // avoid overflow: if total > 292,277 years, just wait forever
-        boolean overflow = millis >= (Long.MAX_VALUE - nanos) / NANOS_PER_MILLI;
-        boolean forever = (millis | nanos) == 0;
-        if (forever | overflow) {
-            join();
-            return;
-        }
-
-        VMThread t = vmThread;
-        if (t == null) {
-            return;
-        }
-
-        synchronized (t) {
-            if (!isAlive()) {
-                return;
-            }
-
-            // guaranteed not to overflow
-            long nanosToWait = millis * NANOS_PER_MILLI + nanos;
-
-            // wait until this thread completes or the timeout has elapsed
-            long start = System.nanoTime();
-            while (true) {
-                t.wait(millis, nanos);
-                if (!isAlive()) {
-                    break;
-                }
-                long nanosElapsed = System.nanoTime() - start;
-                long nanosRemaining = nanosToWait - nanosElapsed;
-                if (nanosRemaining <= 0) {
-                    break;
-                }
-                millis = nanosRemaining / NANOS_PER_MILLI;
-                nanos = (int) (nanosRemaining - millis * NANOS_PER_MILLI);
-            }
-        }
-    }
-
-    /**
-     * Throws {@code UnsupportedOperationException}.
-     * @deprecated Only useful in conjunction with deprecated method {@link Thread#suspend}.
-     */
-    @Deprecated
-    public final void resume() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Calls the <code>run()</code> method of the Runnable object the receiver
-     * holds. If no Runnable is set, does nothing.
-     *
-     * @see Thread#start
-     */
-    public void run() {
-        if (target != null) {
-            target.run();
-        }
-    }
-
-    /**
-     * Set the context ClassLoader for the receiver.
-     *
-     * @param cl The context ClassLoader
-     * @see #getContextClassLoader()
-     */
-    public void setContextClassLoader(ClassLoader cl) {
-        contextClassLoader = cl;
-    }
-
-    /**
-     * Marks this thread as a daemon thread.
-     * A daemon thread only runs as long as there are non-daemon threads running.
-     * When the last non-daemon thread ends, the runtime will exit. This is not
-     * normally relevant to applications with a UI.
-     * @throws IllegalThreadStateException - if this thread has already started.
-     */
-    public final void setDaemon(boolean isDaemon) {
-        checkNotStarted();
-        if (vmThread == null) {
-            daemon = isDaemon;
-        }
-    }
-
-    private void checkNotStarted() {
-        if (hasBeenStarted) {
-            throw new IllegalThreadStateException("Thread already started");
-        }
-    }
-
-    /**
-     * Sets the default uncaught exception handler. This handler is invoked in
-     * case any Thread dies due to an unhandled exception.
-     *
-     * @param handler
-     *            The handler to set or null.
-     */
-    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
-        Thread.defaultUncaughtHandler = handler;
-    }
-
-    /**
-     * Adds a runnable to be invoked upon interruption. If this thread has
-     * already been interrupted, the runnable will be invoked immediately. The
-     * action should be idempotent as it may be invoked multiple times for a
-     * single interruption.
-     *
-     * <p>Each call to this method must be matched with a corresponding call to
-     * {@link #popInterruptAction$}.
-     *
-     * @hide used by NIO
-     */
-    public final void pushInterruptAction$(Runnable interruptAction) {
-        synchronized (interruptActions) {
-            interruptActions.add(interruptAction);
-        }
-
-        if (interruptAction != null && isInterrupted()) {
-            interruptAction.run();
-        }
-    }
-
-    /**
-     * Removes {@code interruptAction} so it is not invoked upon interruption.
-     *
-     * @param interruptAction the pushed action, used to check that the call
-     *     stack is correctly nested.
-     *
-     * @hide used by NIO
-     */
-    public final void popInterruptAction$(Runnable interruptAction) {
-        synchronized (interruptActions) {
-            Runnable removed = interruptActions.remove(interruptActions.size() - 1);
-            if (interruptAction != removed) {
-                throw new IllegalArgumentException(
-                        "Expected " + interruptAction + " but was " + removed);
-            }
-        }
-    }
-
-    /**
-     * Sets the name of the Thread.
-     *
-     * @param threadName the new name for the Thread
-     * @see Thread#getName
-     */
-    public final void setName(String threadName) {
-        if (threadName == null) {
-            throw new NullPointerException("threadName == null");
-        }
-
-        name = threadName;
-        VMThread vmt = this.vmThread;
-        if (vmt != null) {
-            /* notify the VM that the thread name has changed */
-            vmt.nameChanged(threadName);
-        }
-    }
-
-    /**
-     * Sets the priority of this thread. If the requested priority is greater than the
-     * parent thread group's {@link java.lang.ThreadGroup#getMaxPriority}, the group's maximum
-     * priority will be used instead.
-     *
-     * @throws IllegalArgumentException - if the new priority is greater than {@link #MAX_PRIORITY}
-     *     or less than {@link #MIN_PRIORITY}
-     */
-    public final void setPriority(int priority) {
-        if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
-            throw new IllegalArgumentException("Priority out of range: " + priority);
-        }
-
-        if (priority > group.getMaxPriority()) {
-            priority = group.getMaxPriority();
-        }
-
-        this.priority = priority;
-
-        VMThread vmt = this.vmThread;
-        if (vmt != null) {
-            vmt.setPriority(priority);
-        }
-    }
-
-    /**
-     * <p>
-     * Sets the uncaught exception handler. This handler is invoked in case this
-     * Thread dies due to an unhandled exception.
-     * </p>
-     *
-     * @param handler
-     *            The handler to set or <code>null</code>.
-     */
-    public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
-        uncaughtHandler = handler;
-    }
-
-    /**
-     * Causes the thread which sent this message to sleep for the given interval
-     * of time (given in milliseconds). The precision is not guaranteed - the
-     * Thread may sleep more or less than requested.
-     *
-     * @param time
-     *            The time to sleep in milliseconds.
-     * @throws InterruptedException if the current thread has been interrupted.
-     *            The interrupted status of the current thread will be cleared before the exception
-     *            is thrown.
-     * @see Thread#interrupt()
-     */
-    public static void sleep(long time) throws InterruptedException {
-        Thread.sleep(time, 0);
-    }
-
-    /**
-     * Causes the thread which sent this message to sleep for the given interval
-     * of time (given in milliseconds and nanoseconds). The precision is not
-     * guaranteed - the Thread may sleep more or less than requested.
-     *
-     * @param millis
-     *            The time to sleep in milliseconds.
-     * @param nanos
-     *            Extra nanosecond precision
-     * @throws InterruptedException if the current thread has been interrupted.
-     *            The interrupted status of the current thread will be cleared before the exception
-     *            is thrown.
-     * @see Thread#interrupt()
-     */
-    public static void sleep(long millis, int nanos) throws InterruptedException {
-        VMThread.sleep(millis, nanos);
-    }
-
-    /**
-     * Starts the new Thread of execution. The <code>run()</code> method of
-     * the receiver will be called by the receiver Thread itself (and not the
-     * Thread calling <code>start()</code>).
-     *
-     * @throws IllegalThreadStateException - if this thread has already started.
-     * @see Thread#run
-     */
-    public synchronized void start() {
-        checkNotStarted();
-
-        hasBeenStarted = true;
-
-        VMThread.create(this, stackSize);
-    }
-
-    /**
-     * Requests the receiver Thread to stop and throw ThreadDeath. The Thread is
-     * resumed if it was suspended and awakened if it was sleeping, so that it
-     * can proceed to throw ThreadDeath.
-     *
-     * @deprecated Stopping a thread in this manner is unsafe and can
-     * leave your application and the VM in an unpredictable state.
-     */
-    @Deprecated
-    public final void stop() {
-        stop(new ThreadDeath());
-    }
-
-    /**
-     * Throws {@code UnsupportedOperationException}.
-     * @deprecated Stopping a thread in this manner is unsafe and can
-     * leave your application and the VM in an unpredictable state.
-     */
-    @Deprecated
-    public final synchronized void stop(Throwable throwable) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Throws {@code UnsupportedOperationException}.
-     * @deprecated May cause deadlocks.
-     */
-    @Deprecated
-    public final void suspend() {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Returns a string containing a concise, human-readable description of the
-     * Thread. It includes the Thread's name, priority, and group name.
-     *
-     * @return a printable representation for the receiver.
-     */
-    @Override
-    public String toString() {
-        return "Thread[" + name + "," + priority + "," + group.getName() + "]";
-    }
-
-    /**
-     * Causes the calling Thread to yield execution time to another Thread that
-     * is ready to run. The actual scheduling is implementation-dependent.
-     */
-    public static void yield() {
-        VMThread.yield();
-    }
-
-    /**
-     * Indicates whether the current Thread has a monitor lock on the specified
-     * object.
-     *
-     * @param object the object to test for the monitor lock
-     * @return true if the current thread has a monitor lock on the specified
-     *         object; false otherwise
-     */
-    public static boolean holdsLock(Object object) {
-        return currentThread().vmThread.holdsLock(object);
-    }
-
-    /**
-     * Implemented by objects that want to handle cases where a thread is being
-     * terminated by an uncaught exception. Upon such termination, the handler
-     * is notified of the terminating thread and causal exception. If there is
-     * no explicit handler set then the thread's group is the default handler.
-     */
-    public static interface UncaughtExceptionHandler {
-        /**
-         * The thread is being terminated by an uncaught exception. Further
-         * exceptions thrown in this method are prevent the remainder of the
-         * method from executing, but are otherwise ignored.
-         *
-         * @param thread the thread that has an uncaught exception
-         * @param ex the exception that was thrown
-         */
-        void uncaughtException(Thread thread, Throwable ex);
-    }
-
-    /**
-     * Unparks this thread. This unblocks the thread it if it was
-     * previously parked, or indicates that the thread is "preemptively
-     * unparked" if it wasn't already parked. The latter means that the
-     * next time the thread is told to park, it will merely clear its
-     * latent park bit and carry on without blocking.
-     *
-     * <p>See {@link java.util.concurrent.locks.LockSupport} for more
-     * in-depth information of the behavior of this method.</p>
-     *
-     * @hide for Unsafe
-     */
-    public void unpark() {
-        VMThread vmt = vmThread;
-
-        if (vmt == null) {
-            /*
-             * vmThread is null before the thread is start()ed. In
-             * this case, we just go ahead and set the state to
-             * PREEMPTIVELY_UNPARKED. Since this happens before the
-             * thread is started, we don't have to worry about
-             * synchronizing with it.
-             */
-            parkState = ParkState.PREEMPTIVELY_UNPARKED;
-            return;
-        }
-
-        synchronized (vmt) {
-            switch (parkState) {
-                case ParkState.PREEMPTIVELY_UNPARKED: {
-                    /*
-                     * Nothing to do in this case: By definition, a
-                     * preemptively unparked thread is to remain in
-                     * the preemptively unparked state if it is told
-                     * to unpark.
-                     */
-                    break;
-                }
-                case ParkState.UNPARKED: {
-                    parkState = ParkState.PREEMPTIVELY_UNPARKED;
-                    break;
-                }
-                default /*parked*/: {
-                    parkState = ParkState.UNPARKED;
-                    vmt.notifyAll();
-                    break;
-                }
-            }
-        }
-    }
-
-    /**
-     * Parks the current thread for a particular number of nanoseconds, or
-     * indefinitely. If not indefinitely, this method unparks the thread
-     * after the given number of nanoseconds if no other thread unparks it
-     * first. If the thread has been "preemptively unparked," this method
-     * cancels that unparking and returns immediately. This method may
-     * also return spuriously (that is, without the thread being told to
-     * unpark and without the indicated amount of time elapsing).
-     *
-     * <p>See {@link java.util.concurrent.locks.LockSupport} for more
-     * in-depth information of the behavior of this method.</p>
-     *
-     * <p>This method must only be called when <code>this</code> is the current
-     * thread.
-     *
-     * @param nanos number of nanoseconds to park for or <code>0</code>
-     * to park indefinitely
-     * @throws IllegalArgumentException thrown if <code>nanos &lt; 0</code>
-     *
-     * @hide for Unsafe
-     */
-    public void parkFor(long nanos) {
-        VMThread vmt = vmThread;
-
-        if (vmt == null) {
-            // Running threads should always have an associated vmThread.
-            throw new AssertionError();
-        }
-
-        synchronized (vmt) {
-            switch (parkState) {
-                case ParkState.PREEMPTIVELY_UNPARKED: {
-                    parkState = ParkState.UNPARKED;
-                    break;
-                }
-                case ParkState.UNPARKED: {
-                    long millis = nanos / NANOS_PER_MILLI;
-                    nanos %= NANOS_PER_MILLI;
-
-                    parkState = ParkState.PARKED;
-                    try {
-                        vmt.wait(millis, (int) nanos);
-                    } catch (InterruptedException ex) {
-                        interrupt();
-                    } finally {
-                        /*
-                         * Note: If parkState manages to become
-                         * PREEMPTIVELY_UNPARKED before hitting this
-                         * code, it should left in that state.
-                         */
-                        if (parkState == ParkState.PARKED) {
-                            parkState = ParkState.UNPARKED;
-                        }
-                    }
-                    break;
-                }
-                default /*parked*/: {
-                    throw new AssertionError(
-                            "shouldn't happen: attempt to repark");
-                }
-            }
-        }
-    }
-
-    /**
-     * Parks the current thread until the specified system time. This
-     * method attempts to unpark the current thread immediately after
-     * <code>System.currentTimeMillis()</code> reaches the specified
-     * value, if no other thread unparks it first. If the thread has
-     * been "preemptively unparked," this method cancels that
-     * unparking and returns immediately. This method may also return
-     * spuriously (that is, without the thread being told to unpark
-     * and without the indicated amount of time elapsing).
-     *
-     * <p>See {@link java.util.concurrent.locks.LockSupport} for more
-     * in-depth information of the behavior of this method.</p>
-     *
-     * <p>This method must only be called when <code>this</code> is the
-     * current thread.
-     *
-     * @param time the time after which the thread should be unparked,
-     * in absolute milliseconds-since-the-epoch
-     *
-     * @hide for Unsafe
-     */
-    public void parkUntil(long time) {
-        VMThread vmt = vmThread;
-
-        if (vmt == null) {
-            // Running threads should always have an associated vmThread.
-            throw new AssertionError();
-        }
-
-        synchronized (vmt) {
-            /*
-             * Note: This conflates the two time bases of "wall clock"
-             * time and "monotonic uptime" time. However, given that
-             * the underlying system can only wait on monotonic time,
-             * it is unclear if there is any way to avoid the
-             * conflation. The downside here is that if, having
-             * calculated the delay, the wall clock gets moved ahead,
-             * this method may not return until well after the wall
-             * clock has reached the originally designated time. The
-             * reverse problem (the wall clock being turned back)
-             * isn't a big deal, since this method is allowed to
-             * spuriously return for any reason, and this situation
-             * can safely be construed as just such a spurious return.
-             */
-            long delayMillis = time - System.currentTimeMillis();
-
-            if (delayMillis <= 0) {
-                parkState = ParkState.UNPARKED;
-            } else {
-                parkFor(delayMillis * NANOS_PER_MILLI);
-            }
-        }
-    }
-}
diff --git a/libdvm/src/main/java/java/lang/ThreadGroup.java b/libdvm/src/main/java/java/lang/ThreadGroup.java
deleted file mode 100644
index 7fc6b72..0000000
--- a/libdvm/src/main/java/java/lang/ThreadGroup.java
+++ /dev/null
@@ -1,726 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import libcore.util.CollectionUtils;
-
-/**
- * {@code ThreadGroup} is a means of organizing threads into a hierarchical structure.
- * This class is obsolete. See <i>Effective Java</i> Item 73, "Avoid thread groups" for details.
- * @see Thread
- */
-public class ThreadGroup implements Thread.UncaughtExceptionHandler {
-
-    // Name of this ThreadGroup
-    // VM needs this field name for debugging.
-    private String name;
-
-    // Maximum priority for Threads inside this ThreadGroup
-    private int maxPriority = Thread.MAX_PRIORITY;
-
-    // The ThreadGroup to which this ThreadGroup belongs
-    // VM needs this field name for debugging.
-    final ThreadGroup parent;
-
-    /**
-     * Weak references to the threads in this group.
-     * Access is guarded by synchronizing on this field.
-     */
-    private final List<WeakReference<Thread>> threadRefs = new ArrayList<WeakReference<Thread>>(5);
-
-    /**
-     * View of the threads.
-     * Access is guarded by synchronizing on threadRefs.
-     */
-    private final Iterable<Thread> threads = CollectionUtils.dereferenceIterable(threadRefs, true);
-
-    /**
-     * Thread groups. Access is guarded by synchronizing on this field.
-     */
-    private final List<ThreadGroup> groups = new ArrayList<ThreadGroup>(3);
-
-    // Whether this ThreadGroup is a daemon ThreadGroup or not
-    private boolean isDaemon;
-
-    // Whether this ThreadGroup has already been destroyed or not
-    private boolean isDestroyed;
-
-    /* the VM uses these directly; do not rename */
-    static final ThreadGroup mSystem = new ThreadGroup();
-    static final ThreadGroup mMain = new ThreadGroup(mSystem, "main");
-
-    /**
-     * Constructs a new {@code ThreadGroup} with the given name. The new {@code ThreadGroup}
-     * will be child of the {@code ThreadGroup} to which the calling thread belongs.
-     *
-     * @param name the name
-     * @see Thread#currentThread
-     */
-    public ThreadGroup(String name) {
-        this(Thread.currentThread().getThreadGroup(), name);
-    }
-
-    /**
-     * Constructs a new {@code ThreadGroup} with the given name, as a child of the
-     * given {@code ThreadGroup}.
-     *
-     * @param parent the parent
-     * @param name the name
-     * @throws NullPointerException if {@code parent == null}
-     * @throws IllegalThreadStateException if {@code parent} has been
-     *         destroyed already
-     */
-    public ThreadGroup(ThreadGroup parent, String name) {
-        if (parent == null) {
-            throw new NullPointerException("parent == null");
-        }
-        this.name = name;
-        this.parent = parent;
-        if (parent != null) {
-            parent.add(this);
-            this.setMaxPriority(parent.getMaxPriority());
-            if (parent.isDaemon()) {
-                this.setDaemon(true);
-            }
-        }
-    }
-
-    /**
-     * Initialize the special "system" ThreadGroup. Was "main" in Harmony,
-     * but we have an additional group above that in Android.
-     */
-    private ThreadGroup() {
-        this.name = "system";
-        this.parent = null;
-    }
-
-    /**
-     * Returns the number of running {@code Thread}s which are children of this thread group,
-     * directly or indirectly.
-     *
-     * @return the number of children
-     */
-    public int activeCount() {
-        int count = 0;
-        synchronized (threadRefs) {
-            for (Thread thread : threads) {
-                if (thread.isAlive()) {
-                    count++;
-                }
-            }
-        }
-        synchronized (groups) {
-            for (ThreadGroup group : groups) {
-                count += group.activeCount();
-            }
-        }
-        return count;
-    }
-
-    /**
-     * Returns the number of {@code ThreadGroup}s which are children of this group,
-     * directly or indirectly.
-     *
-     * @return the number of children
-     */
-    public int activeGroupCount() {
-        int count = 0;
-        synchronized (groups) {
-            for (ThreadGroup group : groups) {
-                // One for this group & the subgroups
-                count += 1 + group.activeGroupCount();
-            }
-        }
-        return count;
-    }
-
-    /**
-     * Adds a {@code ThreadGroup} to this thread group.
-     *
-     * @param g ThreadGroup to add
-     * @throws IllegalThreadStateException if this group has been destroyed already
-     */
-    private void add(ThreadGroup g) throws IllegalThreadStateException {
-        synchronized (groups) {
-            if (isDestroyed) {
-                throw new IllegalThreadStateException();
-            }
-            groups.add(g);
-        }
-    }
-
-    /**
-     * Does nothing. The definition of this method depends on the deprecated
-     * method {@link #suspend()}. The exact behavior of this call was never
-     * specified.
-     *
-     * @param b Used to control low memory implicit suspension
-     * @return {@code true} (always)
-     *
-     * @deprecated Required deprecated method {@link #suspend()}.
-     */
-    @Deprecated
-    public boolean allowThreadSuspension(boolean b) {
-        // Does not apply to this VM, no-op
-        return true;
-    }
-
-    /**
-     * Does nothing.
-     */
-    public final void checkAccess() {
-    }
-
-    /**
-     * Destroys this thread group and recursively all its subgroups. It is only legal
-     * to destroy a {@code ThreadGroup} that has no threads in it. Any daemon
-     * {@code ThreadGroup} is destroyed automatically when it becomes empty (no threads
-     * or thread groups in it).
-     *
-     * @throws IllegalThreadStateException if this thread group or any of its
-     *         subgroups has been destroyed already or if it still contains
-     *         threads.
-     */
-    public final void destroy() {
-        synchronized (threadRefs) {
-            synchronized (groups) {
-                if (isDestroyed) {
-                    throw new IllegalThreadStateException(
-                            "Thread group was already destroyed: "
-                            + (this.name != null ? this.name : "n/a"));
-                }
-                if (threads.iterator().hasNext()) {
-                    throw new IllegalThreadStateException(
-                            "Thread group still contains threads: "
-                            + (this.name != null ? this.name : "n/a"));
-                }
-                // Call recursively for subgroups
-                while (!groups.isEmpty()) {
-                    // We always get the first element - remember, when the
-                    // child dies it removes itself from our collection. See
-                    // below.
-                    groups.get(0).destroy();
-                }
-
-                if (parent != null) {
-                    parent.remove(this);
-                }
-
-                // Now that the ThreadGroup is really destroyed it can be tagged as so
-                this.isDestroyed = true;
-            }
-        }
-    }
-
-    /*
-     * Auxiliary method that destroys this thread group and recursively all its
-     * subgroups if this is a daemon ThreadGroup.
-     *
-     * @see #destroy
-     * @see #setDaemon
-     * @see #isDaemon
-     */
-    private void destroyIfEmptyDaemon() {
-        // Has to be non-destroyed daemon to make sense
-        synchronized (threadRefs) {
-            if (isDaemon && !isDestroyed && !threads.iterator().hasNext()) {
-                synchronized (groups) {
-                    if (groups.isEmpty()) {
-                        destroy();
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Iterates over all active threads in this group (and its sub-groups) and
-     * stores the threads in the given array. Returns when the array is full or
-     * no more threads remain, whichever happens first.
-     *
-     * <p>Note that this method will silently ignore any threads that don't fit in the
-     * supplied array.
-     *
-     * @param threads the array into which the {@code Thread}s will be copied
-     * @return the number of {@code Thread}s that were copied
-     */
-    public int enumerate(Thread[] threads) {
-        return enumerate(threads, true);
-    }
-
-    /**
-     * Iterates over all active threads in this group (and, optionally, its
-     * sub-groups) and stores the threads in the given array. Returns when the
-     * array is full or no more threads remain, whichever happens first.
-     *
-     * <p>Note that this method will silently ignore any threads that don't fit in the
-     * supplied array.
-     *
-     * @param threads the array into which the {@code Thread}s will be copied
-     * @param recurse indicates whether {@code Thread}s in subgroups should be
-     *        recursively copied as well
-     * @return the number of {@code Thread}s that were copied
-     */
-    public int enumerate(Thread[] threads, boolean recurse) {
-        return enumerateGeneric(threads, recurse, 0, true);
-    }
-
-    /**
-     * Iterates over all thread groups in this group (and its sub-groups) and
-     * and stores the groups in the given array. Returns when the array is full
-     * or no more groups remain, whichever happens first.
-     *
-     * <p>Note that this method will silently ignore any thread groups that don't fit in the
-     * supplied array.
-     *
-     * @param groups the array into which the {@code ThreadGroup}s will be copied
-     * @return the number of {@code ThreadGroup}s that were copied
-     */
-    public int enumerate(ThreadGroup[] groups) {
-        return enumerate(groups, true);
-    }
-
-    /**
-     * Iterates over all thread groups in this group (and, optionally, its
-     * sub-groups) and stores the groups in the given array. Returns when
-     * the array is full or no more groups remain, whichever happens first.
-     *
-     * <p>Note that this method will silently ignore any thread groups that don't fit in the
-     * supplied array.
-     *
-     * @param groups the array into which the {@code ThreadGroup}s will be copied
-     * @param recurse indicates whether {@code ThreadGroup}s in subgroups should be
-     *        recursively copied as well or not
-     * @return the number of {@code ThreadGroup}s that were copied
-     */
-    public int enumerate(ThreadGroup[] groups, boolean recurse) {
-        return enumerateGeneric(groups, recurse, 0, false);
-    }
-
-    /**
-     * Copies into <param>enumeration</param> starting at
-     * <param>enumerationIndex</param> all Threads or ThreadGroups in the
-     * receiver. If <param>recurse</param> is true, recursively enumerate the
-     * elements in subgroups.
-     *
-     * If the array passed as parameter is too small no exception is thrown -
-     * the extra elements are simply not copied.
-     *
-     * @param enumeration array into which the elements will be copied
-     * @param recurse Indicates whether subgroups should be enumerated or not
-     * @param enumerationIndex Indicates in which position of the enumeration
-     *        array we are
-     * @param enumeratingThreads Indicates whether we are enumerating Threads or
-     *        ThreadGroups
-     * @return How many elements were enumerated/copied over
-     */
-    private int enumerateGeneric(Object[] enumeration, boolean recurse, int enumerationIndex,
-            boolean enumeratingThreads) {
-        if (enumeratingThreads) {
-            synchronized (threadRefs) {
-                // walk the references directly so we can iterate in reverse order
-                for (int i = threadRefs.size() - 1; i >= 0; --i) {
-                    Thread thread = threadRefs.get(i).get();
-                    if (thread != null && thread.isAlive()) {
-                        if (enumerationIndex >= enumeration.length) {
-                            return enumerationIndex;
-                        }
-                        enumeration[enumerationIndex++] = thread;
-                    }
-                }
-            }
-        } else {
-            synchronized (groups) {
-                for (int i = groups.size() - 1; i >= 0; --i) {
-                    if (enumerationIndex >= enumeration.length) {
-                        return enumerationIndex;
-                    }
-                    enumeration[enumerationIndex++] = groups.get(i);
-                }
-            }
-        }
-
-        if (recurse) {
-            synchronized (groups) {
-                for (ThreadGroup group : groups) {
-                    if (enumerationIndex >= enumeration.length) {
-                        return enumerationIndex;
-                    }
-                    enumerationIndex = group.enumerateGeneric(enumeration, recurse,
-                            enumerationIndex, enumeratingThreads);
-                }
-            }
-        }
-        return enumerationIndex;
-    }
-
-    /**
-     * Returns the maximum allowed priority for a {@code Thread} in this thread group.
-     *
-     * @return the maximum priority
-     *
-     * @see #setMaxPriority
-     */
-    public final int getMaxPriority() {
-        return maxPriority;
-    }
-
-    /**
-     * Returns the name of this thread group.
-     *
-     * @return the group's name
-     */
-    public final String getName() {
-        return name;
-    }
-
-    /**
-     * Returns this thread group's parent {@code ThreadGroup}. It can be null if this
-     * is the the root ThreadGroup.
-     *
-     * @return the parent
-     */
-    public final ThreadGroup getParent() {
-        return parent;
-    }
-
-    /**
-     * Interrupts every {@code Thread} in this group and recursively in all its
-     * subgroups.
-     *
-     * @see Thread#interrupt
-     */
-    public final void interrupt() {
-        synchronized (threadRefs) {
-            for (Thread thread : threads) {
-                thread.interrupt();
-            }
-        }
-        synchronized (groups) {
-            for (ThreadGroup group : groups) {
-                group.interrupt();
-            }
-        }
-    }
-
-    /**
-     * Checks whether this thread group is a daemon {@code ThreadGroup}.
-     *
-     * @return true if this thread group is a daemon {@code ThreadGroup}
-     *
-     * @see #setDaemon
-     * @see #destroy
-     */
-    public final boolean isDaemon() {
-        return isDaemon;
-    }
-
-    /**
-     * Checks whether this thread group has already been destroyed.
-     *
-     * @return true if this thread group has already been destroyed
-     * @see #destroy
-     */
-    public synchronized boolean isDestroyed() {
-        return isDestroyed;
-    }
-
-    /**
-     * Outputs to {@code System.out} a text representation of the
-     * hierarchy of {@code Thread}s and {@code ThreadGroup}s in this thread group (and recursively).
-     * Proper indentation is used to show the nesting of groups inside groups
-     * and threads inside groups.
-     */
-    public void list() {
-        // We start in a fresh line
-        System.out.println();
-        list(0);
-    }
-
-    /*
-     * Outputs to {@code System.out}a text representation of the
-     * hierarchy of Threads and ThreadGroups in this thread group (and recursively).
-     * The indentation will be four spaces per level of nesting.
-     *
-     * @param levels How many levels of nesting, so that proper indentation can
-     * be output.
-     */
-    private void list(int levels) {
-        indent(levels);
-        System.out.println(this.toString());
-
-        ++levels;
-        synchronized (threadRefs) {
-            for (Thread thread : threads) {
-                indent(levels);
-                System.out.println(thread);
-            }
-        }
-        synchronized (groups) {
-            for (ThreadGroup group : groups) {
-                group.list(levels);
-            }
-        }
-    }
-
-    private void indent(int levels) {
-        for (int i = 0; i < levels; i++) {
-            System.out.print("    "); // 4 spaces for each level
-        }
-    }
-
-    /**
-     * Checks whether this thread group is a direct or indirect parent group of a
-     * given {@code ThreadGroup}.
-     *
-     * @param g the potential child {@code ThreadGroup}
-     * @return true if this thread group is parent of {@code g}
-     */
-    public final boolean parentOf(ThreadGroup g) {
-        while (g != null) {
-            if (this == g) {
-                return true;
-            }
-            g = g.parent;
-        }
-        return false;
-    }
-
-    /**
-     * Removes an immediate subgroup.
-     *
-     * @param g ThreadGroup to remove
-     *
-     * @see #add(Thread)
-     * @see #add(ThreadGroup)
-     */
-    private void remove(ThreadGroup g) {
-        synchronized (groups) {
-            for (Iterator<ThreadGroup> i = groups.iterator(); i.hasNext(); ) {
-                ThreadGroup threadGroup = i.next();
-                if (threadGroup.equals(g)) {
-                    i.remove();
-                    break;
-                }
-            }
-        }
-        destroyIfEmptyDaemon();
-    }
-
-    /**
-     * Resumes every thread in this group and recursively in all its
-     * subgroups.
-     *
-     * @see Thread#resume
-     * @see #suspend
-     *
-     * @deprecated Requires deprecated method {@link Thread#resume()}.
-     */
-    @SuppressWarnings("deprecation")
-    @Deprecated
-    public final void resume() {
-        synchronized (threadRefs) {
-            for (Thread thread : threads) {
-                thread.resume();
-            }
-        }
-        synchronized (groups) {
-            for (ThreadGroup group : groups) {
-                group.resume();
-            }
-        }
-    }
-
-    /**
-     * Sets whether this is a daemon {@code ThreadGroup} or not. Daemon
-     * thread groups are automatically destroyed when they become empty.
-     *
-     * @param isDaemon the new value
-     * @see #isDaemon
-     * @see #destroy
-     */
-    public final void setDaemon(boolean isDaemon) {
-        this.isDaemon = isDaemon;
-    }
-
-    /**
-     * Configures the maximum allowed priority for a {@code Thread} in this group and
-     * recursively in all its subgroups.
-     *
-     * <p>A caller can never increase the maximum priority of a thread group.
-     * Such an attempt will not result in an exception, it will
-     * simply leave the thread group with its current maximum priority.
-     *
-     * @param newMax the new maximum priority to be set
-     *
-     * @throws IllegalArgumentException if the new priority is greater than
-     *         Thread.MAX_PRIORITY or less than Thread.MIN_PRIORITY
-     *
-     * @see #getMaxPriority
-     */
-    public final void setMaxPriority(int newMax) {
-        if (newMax <= this.maxPriority) {
-            if (newMax < Thread.MIN_PRIORITY) {
-                newMax = Thread.MIN_PRIORITY;
-            }
-
-            int parentPriority = parent == null ? newMax : parent.getMaxPriority();
-            this.maxPriority = parentPriority <= newMax ? parentPriority : newMax;
-            synchronized (groups) {
-                for (ThreadGroup group : groups) {
-                    group.setMaxPriority(newMax);
-                }
-            }
-        }
-    }
-
-    /**
-     * Stops every thread in this group and recursively in all its subgroups.
-     *
-     * @see Thread#stop()
-     * @see Thread#stop(Throwable)
-     * @see ThreadDeath
-     *
-     * @deprecated Requires deprecated method {@link Thread#stop()}.
-     */
-    @SuppressWarnings("deprecation")
-    @Deprecated
-    public final void stop() {
-        if (stopHelper()) {
-            Thread.currentThread().stop();
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    private boolean stopHelper() {
-        boolean stopCurrent = false;
-        synchronized (threadRefs) {
-            Thread current = Thread.currentThread();
-            for (Thread thread : threads) {
-                if (thread == current) {
-                    stopCurrent = true;
-                } else {
-                    thread.stop();
-                }
-            }
-        }
-        synchronized (groups) {
-            for (ThreadGroup group : groups) {
-                stopCurrent |= group.stopHelper();
-            }
-        }
-        return stopCurrent;
-    }
-
-    /**
-     * Suspends every thread in this group and recursively in all its
-     * subgroups.
-     *
-     * @see Thread#suspend
-     * @see #resume
-     *
-     * @deprecated Requires deprecated method {@link Thread#suspend()}.
-     */
-    @SuppressWarnings("deprecation")
-    @Deprecated
-    public final void suspend() {
-        if (suspendHelper()) {
-            Thread.currentThread().suspend();
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    private boolean suspendHelper() {
-        boolean suspendCurrent = false;
-        synchronized (threadRefs) {
-            Thread current = Thread.currentThread();
-            for (Thread thread : threads) {
-                if (thread == current) {
-                    suspendCurrent = true;
-                } else {
-                    thread.suspend();
-                }
-            }
-        }
-        synchronized (groups) {
-            for (ThreadGroup group : groups) {
-                suspendCurrent |= group.suspendHelper();
-            }
-        }
-        return suspendCurrent;
-    }
-
-    @Override
-    public String toString() {
-        return getClass().getName() + "[name=" + getName()
-                + ",maxPriority=" + getMaxPriority() + "]";
-    }
-
-    /**
-     * Handles uncaught exceptions. Any uncaught exception in any {@code Thread}
-     * is forwarded to the thread's {@code ThreadGroup} by invoking this
-     * method.
-     *
-     * <p>New code should use {@link Thread#setUncaughtExceptionHandler} instead of thread groups.
-     *
-     * @param t the Thread that terminated with an uncaught exception
-     * @param e the uncaught exception itself
-     */
-    public void uncaughtException(Thread t, Throwable e) {
-        if (parent != null) {
-            parent.uncaughtException(t, e);
-        } else if (Thread.getDefaultUncaughtExceptionHandler() != null) {
-            // TODO The spec is unclear regarding this. What do we do?
-            Thread.getDefaultUncaughtExceptionHandler().uncaughtException(t, e);
-        } else if (!(e instanceof ThreadDeath)) {
-            // No parent group, has to be 'system' Thread Group
-            e.printStackTrace(System.err);
-        }
-    }
-
-    /**
-     * Called by the Thread constructor.
-     */
-    final void addThread(Thread thread) throws IllegalThreadStateException {
-        synchronized (threadRefs) {
-            if (isDestroyed) {
-                throw new IllegalThreadStateException();
-            }
-            threadRefs.add(new WeakReference<Thread>(thread));
-        }
-    }
-
-    /**
-     * Called by the VM when a Thread dies.
-     */
-    final void removeThread(Thread thread) throws IllegalThreadStateException {
-        synchronized (threadRefs) {
-            for (Iterator<Thread> i = threads.iterator(); i.hasNext(); ) {
-                if (i.next().equals(thread)) {
-                    i.remove();
-                    break;
-                }
-            }
-        }
-        destroyIfEmptyDaemon();
-    }
-}
diff --git a/libdvm/src/main/java/java/lang/VMClassLoader.java b/libdvm/src/main/java/java/lang/VMClassLoader.java
deleted file mode 100644
index d7162c6..0000000
--- a/libdvm/src/main/java/java/lang/VMClassLoader.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-
-class VMClassLoader {
-
-    /**
-     * Get a resource from a file in the bootstrap class path.
-     *
-     * It would be simpler to just walk through the class path elements
-     * ourselves, but that would require reopening Jar files.
-     *
-     * We assume that the bootclasspath can't change once the VM has
-     * started.  This assumption seems to be supported by the spec.
-     */
-    static URL getResource(String name) {
-        int numEntries = getBootClassPathSize();
-        for (int i = 0; i < numEntries; i++) {
-            String urlStr = getBootClassPathResource(name, i);
-            if (urlStr != null) {
-                try {
-                    return new URL(urlStr);
-                } catch (MalformedURLException mue) {
-                    mue.printStackTrace();
-                    // unexpected; keep going
-                }
-            }
-        }
-        return null;
-    }
-
-    /*
-     * Get an enumeration with all matching resources.
-     */
-    static List<URL> getResources(String name) {
-        ArrayList<URL> list = new ArrayList<URL>();
-        int numEntries = getBootClassPathSize();
-        for (int i = 0; i < numEntries; i++) {
-            String urlStr = getBootClassPathResource(name, i);
-            if (urlStr != null) {
-                try {
-                    list.add(new URL(urlStr));
-                } catch (MalformedURLException mue) {
-                    mue.printStackTrace();
-                    // unexpected; keep going
-                }
-            }
-        }
-        return list;
-    }
-
-    /**
-     * Load class with bootstrap class loader.
-     */
-    native static Class loadClass(String name, boolean resolve) throws ClassNotFoundException;
-
-    native static Class getPrimitiveClass(char type);
-
-    native static Class findLoadedClass(ClassLoader cl, String name);
-
-    /**
-     * Boot class path manipulation, for getResources().
-     */
-    native private static int getBootClassPathSize();
-    native private static String getBootClassPathResource(String name, int index);
-}
diff --git a/libdvm/src/main/java/java/lang/VMThread.java b/libdvm/src/main/java/java/lang/VMThread.java
deleted file mode 100644
index 01f6ee3..0000000
--- a/libdvm/src/main/java/java/lang/VMThread.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-class VMThread {
-    Thread thread;
-    int vmData;
-
-    VMThread(Thread t) {
-        thread = t;
-    }
-
-    native static void create(Thread t, long stackSize);
-
-    static native Thread currentThread();
-    static native boolean interrupted();
-    static native void sleep (long msec, int nsec) throws InterruptedException;
-    static native void yield();
-
-    native void interrupt();
-
-    native boolean isInterrupted();
-
-    /**
-     *  Starts the VMThread (and thus the Java Thread) with the given
-     *  stack size.
-     */
-    void start(long stackSize) {
-        VMThread.create(thread, stackSize);
-    }
-
-    /**
-     * Queries whether this Thread holds a monitor lock on the
-     * given object.
-     */
-    native boolean holdsLock(Object object);
-
-    native void setPriority(int newPriority);
-    native int getStatus();
-
-    /**
-     * Holds a mapping from native Thread statuses to Java one. Required for
-     * translating back the result of getStatus().
-     */
-    static final Thread.State[] STATE_MAP = new Thread.State[] {
-        Thread.State.TERMINATED,     // ZOMBIE
-        Thread.State.RUNNABLE,       // RUNNING
-        Thread.State.TIMED_WAITING,  // TIMED_WAIT
-        Thread.State.BLOCKED,        // MONITOR
-        Thread.State.WAITING,        // WAIT
-        Thread.State.NEW,            // INITIALIZING
-        Thread.State.NEW,            // STARTING
-        Thread.State.RUNNABLE,       // NATIVE
-        Thread.State.WAITING,        // VMWAIT
-        Thread.State.RUNNABLE        // SUSPENDED
-    };
-
-    /**
-     * Tell the VM that the thread's name has changed.  This is useful for
-     * DDMS, which would otherwise be oblivious to Thread.setName calls.
-     */
-    native void nameChanged(String newName);
-}
diff --git a/libdvm/src/main/java/java/lang/ref/Reference.java b/libdvm/src/main/java/java/lang/ref/Reference.java
deleted file mode 100644
index bd63535..0000000
--- a/libdvm/src/main/java/java/lang/ref/Reference.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.ref;
-
-/**
- * Provides an abstract class which describes behavior common to all reference
- * objects. It is not possible to create immediate subclasses of
- * {@code Reference} in addition to the ones provided by this package. It is
- * also not desirable to do so, since references require very close cooperation
- * with the system's garbage collector. The existing, specialized reference
- * classes should be used instead.
- *
- * <p>Three different type of references exist, each being weaker than the preceding one:
- * {@link java.lang.ref.SoftReference}, {@link java.lang.ref.WeakReference}, and
- * {@link java.lang.ref.PhantomReference}. "Weakness" here means that less restrictions are
- * being imposed on the garbage collector as to when it is allowed to
- * actually garbage-collect the referenced object.
- *
- * <p>In order to use reference objects properly it is important to understand
- * the different types of reachability that trigger their clearing and
- * enqueueing. The following table lists these, from strongest to weakest.
- * For each row, an object is said to have the reachability on the left side
- * if (and only if) it fulfills all of the requirements on the right side. In
- * all rows, consider the <em>root set</em> to be a set of references that
- * are "resistant" to garbage collection (that is, running threads, method
- * parameters, local variables, static fields and the like).
- *
- * <p><table>
- * <tr>
- * <td>Strongly reachable</td>
- * <td> <ul>
- * <li>There exists at least one path from the root set to the object that does not traverse any
- * instance of a {@code java.lang.ref.Reference} subclass.
- * </li>
- * </ul> </td>
- * </tr>
- *
- * <tr>
- * <td>Softly reachable</td>
- * <td> <ul>
- * <li>The object is not strongly reachable.</li>
- * <li>There exists at least one path from the root set to the object that does traverse
- * a {@code java.lang.ref.SoftReference} instance, but no {@code java.lang.ref.WeakReference}
- * or {@code java.lang.ref.PhantomReference} instances.</li>
- * </ul> </td>
- * </tr>
- *
- * <tr>
- * <td>Weakly reachable</td>
- * <td> <ul>
- * <li>The object is neither strongly nor softly reachable.</li>
- * <li>There exists at least one path from the root set to the object that does traverse a
- * {@code java.lang.ref.WeakReference} instance, but no {@code java.lang.ref.PhantomReference}
- * instances.</li>
- * </ul> </td>
- * </tr>
- *
- * <tr>
- * <td>Phantom-reachable</td>
- * <td> <ul>
- * <li>The object is neither strongly, softly, nor weakly reachable.</li>
- * <li>The object is referenced by a {@code java.lang.ref.PhantomReference} instance.</li>
- * <li>The object has already been finalized.</li>
- * </ul> </td>
- * </tr>
- * </table>
- */
-public abstract class Reference<T> {
-
-    /**
-     * The object to which this reference refers.
-     * VM requirement: this field <em>must</em> be called "referent"
-     * and be an object.
-     */
-    volatile T referent;
-
-    /**
-     * If non-null, the queue on which this reference will be enqueued
-     * when the referent is appropriately reachable.
-     * VM requirement: this field <em>must</em> be called "queue"
-     * and be a java.lang.ref.ReferenceQueue.
-     */
-    volatile ReferenceQueue<? super T> queue;
-
-    /**
-     * Used internally by java.lang.ref.ReferenceQueue.
-     * VM requirement: this field <em>must</em> be called "queueNext"
-     * and be a java.lang.ref.Reference.
-     */
-    @SuppressWarnings("unchecked")
-    volatile Reference queueNext;
-
-    /**
-     * Used internally by the VM.  This field forms a circular and
-     * singly linked list of reference objects discovered by the
-     * garbage collector and awaiting processing by the reference
-     * queue thread.
-     *
-     * @hide
-     */
-    public volatile Reference<?> pendingNext;
-
-    /**
-     * Constructs a new instance of this class.
-     */
-    Reference() {
-    }
-
-    Reference(T r, ReferenceQueue<? super T> q) {
-        referent = r;
-        queue = q;
-    }
-
-    /**
-     * Makes the referent {@code null}. This does not force the reference
-     * object to be enqueued.
-     */
-    public void clear() {
-        referent = null;
-    }
-
-    /**
-     * Adds an object to its reference queue.
-     *
-     * @return {@code true} if this call has caused the {@code Reference} to
-     * become enqueued, or {@code false} otherwise
-     *
-     * @hide
-     */
-    public final synchronized boolean enqueueInternal() {
-        if (queue != null && queueNext == null) {
-            queue.enqueue(this);
-            queue = null;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Forces the reference object to be enqueued if it has been associated with
-     * a queue.
-     *
-     * @return {@code true} if this call has caused the {@code Reference} to
-     * become enqueued, or {@code false} otherwise
-     */
-    public boolean enqueue() {
-        return enqueueInternal();
-    }
-
-    /**
-     * Returns the referent of the reference object.
-     *
-     * @return the referent to which reference refers, or {@code null} if the
-     *         object has been cleared.
-     */
-    public T get() {
-        return referent;
-    }
-
-    /**
-     * Checks whether the reference object has been enqueued.
-     *
-     * @return {@code true} if the {@code Reference} has been enqueued, {@code
-     *         false} otherwise
-     */
-    public boolean isEnqueued() {
-        return queueNext != null;
-    }
-
-}
diff --git a/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java b/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
deleted file mode 100644
index f3d96af..0000000
--- a/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.reflect;
-
-import java.lang.annotation.Annotation;
-import java.util.Hashtable;
-import org.apache.harmony.kernel.vm.StringUtils;
-
-/**
- * {@code AccessibleObject} is the superclass of all member reflection classes
- * (Field, Constructor, Method). AccessibleObject provides the ability to toggle
- * a flag controlling access checks for these objects. By default, accessing a
- * member (for example, setting a field or invoking a method) checks the
- * validity of the access (for example, invoking a private method from outside
- * the defining class is prohibited) and throws IllegalAccessException if the
- * operation is not permitted. If the accessible flag is set to true, these
- * checks are omitted. This allows privileged code, such as Java object
- * serialization, object inspectors, and debuggers to have complete access to
- * objects.
- *
- * @see Field
- * @see Constructor
- * @see Method
- */
-public class AccessibleObject implements AnnotatedElement {
-
-    /**
-     * If true, object is accessible, bypassing normal access checks
-     */
-    boolean flag = false;
-
-    // Holds a mapping from Java type names to native type codes.
-    static Hashtable<String, String> trans;
-
-    static {
-        trans = new Hashtable<String, String>(9);
-        trans.put("byte", "B");
-        trans.put("char", "C");
-        trans.put("short", "S");
-        trans.put("int", "I");
-        trans.put("long", "J");
-        trans.put("float", "F");
-        trans.put("double", "D");
-        trans.put("void", "V");
-        trans.put("boolean", "Z");
-    }
-
-    /**
-     * Attempts to set the value of the accessible flag for all the objects in
-     * the array provided. Setting this
-     * flag to {@code false} will enable access checks, setting to {@code true}
-     * will disable them.
-     *
-     * @param objects
-     *            the accessible objects
-     * @param flag
-     *            the new value for the accessible flag
-     *
-     * @see #setAccessible(boolean)
-     */
-    public static void setAccessible(AccessibleObject[] objects, boolean flag) {
-        for (AccessibleObject object : objects) {
-            object.flag = flag;
-        }
-    }
-
-    /**
-     * Constructs a new {@code AccessibleObject} instance. {@code
-     * AccessibleObject} instances can only be constructed by the virtual
-     * machine.
-     */
-    protected AccessibleObject() {
-    }
-
-    /**
-     * Indicates whether this object is accessible without access checks being
-     * performed. Returns the accessible flag.
-     *
-     * @return {@code true} if this object is accessible without access
-     *         checks, {@code false} otherwise
-     */
-    public boolean isAccessible() {
-        return flag;
-    }
-
-    /**
-     * Attempts to set the value of the accessible flag. Setting this flag to
-     * {@code false} will enable access checks, setting to {@code true} will
-     * disable them.
-     *
-     * @param flag
-     *            the new value for the accessible flag
-     */
-    public void setAccessible(boolean flag) {
-        this.flag = flag;
-    }
-
-    public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    public Annotation[] getDeclaredAnnotations() {
-        throw new UnsupportedOperationException();
-    }
-
-    public Annotation[] getAnnotations() {
-        // for all but Class, getAnnotations == getDeclaredAnnotations
-        return getDeclaredAnnotations();
-    }
-
-    public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Returns the signature for a class. This is the kind of signature used
-     * internally by the JVM, with one-character codes representing the basic
-     * types. It is not suitable for printing.
-     *
-     * @param clazz
-     *            the class for which a signature is required
-     *
-     * @return The signature as a string
-     */
-    String getSignature(Class<?> clazz) {
-        String result = "";
-        String nextType = clazz.getName();
-
-        if(trans.containsKey(nextType)) {
-            result = trans.get(nextType);
-        } else {
-            if(clazz.isArray()) {
-                result = "[" + getSignature(clazz.getComponentType());
-            } else {
-                result = "L" + nextType + ";";
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Returns a printable String consisting of the canonical names of the
-     * classes contained in an array. The form is that used in parameter and
-     * exception lists, that is, the class or type names are separated by
-     * commas.
-     *
-     * @param types
-     *            the array of classes
-     *
-     * @return The String of names
-     */
-    String toString(Class<?>[] types) {
-        StringBuilder result = new StringBuilder();
-
-        if (types.length != 0) {
-            appendTypeName(result, types[0]);
-            for (int i = 1; i < types.length; i++) {
-                result.append(',');
-                appendTypeName(result, types[i]);
-            }
-        }
-
-        return result.toString();
-    }
-
-    /**
-     * Gets the Signature attribute for this instance. Returns {@code null}
-     * if not found.
-     */
-    /*package*/ String getSignatureAttribute() {
-        /*
-         * Note: This method would have been declared abstract, but the
-         * standard API lists this class as concrete.
-         */
-        throw new UnsupportedOperationException();
-    }
-
-    /**
-     * Retrieve the signature attribute from an arbitrary class.  This is
-     * the same as Class.getSignatureAttribute(), but it can be used from
-     * the java.lang.reflect package.
-     */
-    /*package*/ static String getClassSignatureAttribute(Class clazz) {
-        Object[] annotation = getClassSignatureAnnotation(clazz);
-
-        if (annotation == null) {
-            return null;
-        }
-
-        return StringUtils.combineStrings(annotation);
-    }
-
-    /**
-     * Retrieve the signature annotation from an arbitrary class.  This is
-     * the same as Class.getSignatureAttribute(), but it can be used from
-     * the java.lang.reflect package.
-     */
-    private static native Object[] getClassSignatureAnnotation(Class clazz);
-
-    /**
-     * Appends the best {@link #toString} name for {@code c} to {@code out}.
-     * This works around the fact that {@link Class#getName} is lousy for
-     * primitive arrays (it writes "[C" instead of "char[]") and {@link
-     * Class#getCanonicalName()} is lousy for nested classes (it uses a "."
-     * separator rather than a "$" separator).
-     */
-    void appendTypeName(StringBuilder out, Class<?> c) {
-        int dimensions = 0;
-        while (c.isArray()) {
-            c = c.getComponentType();
-            dimensions++;
-        }
-        out.append(c.getName());
-        for (int d = 0; d < dimensions; d++) {
-            out.append("[]");
-        }
-    }
-
-    /**
-     * Appends names of the specified array classes to the buffer. The array
-     * elements may represent a simple type, a reference type or an array type.
-     * Output format: java.lang.Object[], java.io.File, void
-     *
-     * @param types array of classes to print the names
-     * @throws NullPointerException if any of the arguments is null
-     */
-    void appendArrayGenericType(StringBuilder sb, Type[] types) {
-        if (types.length > 0) {
-            appendGenericType(sb, types[0]);
-            for (int i = 1; i < types.length; i++) {
-                sb.append(',');
-                appendGenericType(sb, types[i]);
-            }
-        }
-    }
-
-    /**
-     * Appends the generic type representation to the buffer.
-     *
-     * @param sb buffer
-     * @param obj the generic type which representation should be appended to the buffer
-     *
-     * @throws NullPointerException if any of the arguments is null
-     */
-    void appendGenericType(StringBuilder sb, Type obj) {
-        if (obj instanceof TypeVariable) {
-            sb.append(((TypeVariable)obj).getName());
-        } else if (obj instanceof ParameterizedType) {
-            sb.append(obj.toString());
-        } else if (obj instanceof GenericArrayType) { //XXX: is it a working branch?
-            Type simplified = ((GenericArrayType)obj).getGenericComponentType();
-            appendGenericType(sb, simplified);
-            sb.append("[]");
-        } else if (obj instanceof Class) {
-            Class c = ((Class<?>)obj);
-            if (c.isArray()){
-                String as[] = c.getName().split("\\[");
-                int len = as.length-1;
-                if (as[len].length() > 1){
-                    sb.append(as[len].substring(1, as[len].length()-1));
-                } else {
-                    char ch = as[len].charAt(0);
-                    if (ch == 'I')
-                        sb.append("int");
-                    else if (ch == 'B')
-                        sb.append("byte");
-                    else if (ch == 'J')
-                        sb.append("long");
-                    else if (ch == 'F')
-                        sb.append("float");
-                    else if (ch == 'D')
-                        sb.append("double");
-                    else if (ch == 'S')
-                        sb.append("short");
-                    else if (ch == 'C')
-                        sb.append("char");
-                    else if (ch == 'Z')
-                        sb.append("boolean");
-                    else if (ch == 'V') //XXX: is it a working branch?
-                        sb.append("void");
-                }
-                for (int i = 0; i < len; i++){
-                    sb.append("[]");
-                }
-            } else {
-                sb.append(c.getName());
-            }
-        }
-    }
-}
diff --git a/libdvm/src/main/java/java/lang/reflect/Constructor.java b/libdvm/src/main/java/java/lang/reflect/Constructor.java
deleted file mode 100644
index acce44f..0000000
--- a/libdvm/src/main/java/java/lang/reflect/Constructor.java
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.reflect;
-
-import java.lang.annotation.Annotation;
-import libcore.util.EmptyArray;
-import org.apache.harmony.kernel.vm.StringUtils;
-import libcore.reflect.GenericSignatureParser;
-import libcore.reflect.ListOfTypes;
-import libcore.reflect.Types;
-
-/**
- * This class represents a constructor. Information about the constructor can be
- * accessed, and the constructor can be invoked dynamically.
- *
- * @param <T> the class that declares this constructor
- */
-public final class Constructor<T> extends AccessibleObject implements GenericDeclaration,
-        Member {
-
-    Class<T> declaringClass;
-
-    Class<?>[] parameterTypes;
-
-    Class<?>[] exceptionTypes;
-
-    ListOfTypes genericExceptionTypes;
-    ListOfTypes genericParameterTypes;
-    TypeVariable<Constructor<T>>[] formalTypeParameters;
-    private volatile boolean genericTypesAreInitialized = false;
-
-    private synchronized void initGenericTypes() {
-        if (!genericTypesAreInitialized) {
-            String signatureAttribute = getSignatureAttribute();
-            GenericSignatureParser parser = new GenericSignatureParser(
-                    declaringClass.getClassLoader());
-            parser.parseForConstructor(this, signatureAttribute, exceptionTypes);
-            formalTypeParameters = parser.formalTypeParameters;
-            genericParameterTypes = parser.parameterTypes;
-            genericExceptionTypes = parser.exceptionTypes;
-            genericTypesAreInitialized = true;
-        }
-    }
-
-    int slot;
-
-    private int methodDexIndex;
-
-    /**
-     * Prevent this class from being instantiated.
-     */
-    private Constructor(){
-        //do nothing
-    }
-
-    /**
-     * Creates an instance of the class. Only called from native code, thus
-     * private.
-     *
-     * @param declaringClass
-     *            the class this constructor object belongs to
-     * @param ptypes
-     *            the parameter types of the constructor
-     * @param extypes
-     *            the exception types of the constructor
-     * @param slot
-     *            the slot of the constructor inside the VM class structure
-     */
-    private Constructor(Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot, int methodDexIndex) {
-        this.declaringClass = declaringClass;
-        this.parameterTypes = ptypes;
-        this.exceptionTypes = extypes;          // may be null
-        this.slot = slot;
-        this.methodDexIndex = methodDexIndex;
-    }
-
-    /** @hide */
-    public int getDexMethodIndex() {
-        return methodDexIndex;
-    }
-
-    @Override /*package*/ String getSignatureAttribute() {
-        Object[] annotation = Method.getSignatureAnnotation(declaringClass, slot);
-
-        if (annotation == null) {
-            return null;
-        }
-
-        return StringUtils.combineStrings(annotation);
-    }
-
-    public TypeVariable<Constructor<T>>[] getTypeParameters() {
-        initGenericTypes();
-        return formalTypeParameters.clone();
-    }
-
-    /**
-     * Returns the string representation of the constructor's declaration,
-     * including the type parameters.
-     *
-     * @return the string representation of the constructor's declaration
-     */
-    public String toGenericString() {
-        StringBuilder sb = new StringBuilder(80);
-        initGenericTypes();
-        // append modifiers if any
-        int modifier = getModifiers();
-        if (modifier != 0) {
-            sb.append(Modifier.toString(modifier & ~Modifier.VARARGS)).append(' ');
-        }
-        // append type parameters
-        if (formalTypeParameters != null && formalTypeParameters.length > 0) {
-            sb.append('<');
-            for (int i = 0; i < formalTypeParameters.length; i++) {
-                appendGenericType(sb, formalTypeParameters[i]);
-                if (i < formalTypeParameters.length - 1) {
-                    sb.append(",");
-                }
-            }
-            sb.append("> ");
-        }
-        // append constructor name
-        appendTypeName(sb, getDeclaringClass());
-        // append parameters
-        sb.append('(');
-        appendArrayGenericType(sb, Types.getTypeArray(genericParameterTypes, false));
-        sb.append(')');
-        // append exceptions if any
-        Type[] genericExceptionTypeArray = Types.getTypeArray(genericExceptionTypes, false);
-        if (genericExceptionTypeArray.length > 0) {
-            sb.append(" throws ");
-            appendArrayGenericType(sb, genericExceptionTypeArray);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns the generic parameter types as an array of {@code Type}
-     * instances, in declaration order. If this constructor has no generic
-     * parameters, an empty array is returned.
-     *
-     * @return the parameter types
-     *
-     * @throws GenericSignatureFormatError
-     *             if the generic constructor signature is invalid
-     * @throws TypeNotPresentException
-     *             if any parameter type points to a missing type
-     * @throws MalformedParameterizedTypeException
-     *             if any parameter type points to a type that cannot be
-     *             instantiated for some reason
-     */
-    public Type[] getGenericParameterTypes() {
-        initGenericTypes();
-        return Types.getTypeArray(genericParameterTypes, true);
-    }
-
-    /**
-     * Returns the exception types as an array of {@code Type} instances. If
-     * this constructor has no declared exceptions, an empty array will be
-     * returned.
-     *
-     * @return an array of generic exception types
-     *
-     * @throws GenericSignatureFormatError
-     *             if the generic constructor signature is invalid
-     * @throws TypeNotPresentException
-     *             if any exception type points to a missing type
-     * @throws MalformedParameterizedTypeException
-     *             if any exception type points to a type that cannot be
-     *             instantiated for some reason
-     */
-    public Type[] getGenericExceptionTypes() {
-        initGenericTypes();
-        return Types.getTypeArray(genericExceptionTypes, true);
-    }
-
-    @Override
-    public Annotation[] getDeclaredAnnotations() {
-        return Method.getDeclaredAnnotations(declaringClass, slot);
-    }
-
-    @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-        return Method.getAnnotation(declaringClass, slot, annotationType);
-    }
-
-    @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-        return Method.isAnnotationPresent(declaringClass, slot, annotationType);
-    }
-
-    /**
-     * Returns an array of arrays that represent the annotations of the formal
-     * parameters of this constructor. If there are no parameters on this
-     * constructor, then an empty array is returned. If there are no annotations
-     * set, then an array of empty arrays is returned.
-     *
-     * @return an array of arrays of {@code Annotation} instances
-     */
-    public Annotation[][] getParameterAnnotations() {
-        Annotation[][] parameterAnnotations
-                = Method.getParameterAnnotations(declaringClass, slot);
-        if (parameterAnnotations.length == 0) {
-            return Method.noAnnotations(parameterTypes.length);
-        }
-        return parameterAnnotations;
-    }
-
-    /**
-     * Indicates whether or not this constructor takes a variable number of
-     * arguments.
-     *
-     * @return {@code true} if a vararg is declare, otherwise
-     *         {@code false}
-     */
-    public boolean isVarArgs() {
-        int mods = Method.getMethodModifiers(declaringClass, slot);
-        return (mods & Modifier.VARARGS) != 0;
-    }
-
-    /**
-     * Indicates whether or not this constructor is synthetic (artificially
-     * introduced by the compiler).
-     *
-     * @return {@code true} if this constructor is synthetic, {@code false}
-     *         otherwise
-     */
-    public boolean isSynthetic() {
-        int mods = Method.getMethodModifiers(declaringClass, slot);
-        return (mods & Modifier.SYNTHETIC) != 0;
-    }
-
-    /**
-     * Indicates whether or not the specified {@code object} is equal to this
-     * constructor. To be equal, the specified object must be an instance
-     * of {@code Constructor} with the same declaring class and parameter types
-     * as this constructor.
-     *
-     * @param object
-     *            the object to compare
-     *
-     * @return {@code true} if the specified object is equal to this
-     *         constructor, {@code false} otherwise
-     *
-     * @see #hashCode
-     */
-    @Override
-    public boolean equals(Object object) {
-        return object instanceof Constructor && toString().equals(object.toString());
-    }
-
-    /**
-     * Returns the class that declares this constructor.
-     *
-     * @return the declaring class
-     */
-    public Class<T> getDeclaringClass() {
-        return declaringClass;
-    }
-
-    /**
-     * Returns the exception types as an array of {@code Class} instances. If
-     * this constructor has no declared exceptions, an empty array will be
-     * returned.
-     *
-     * @return the declared exception classes
-     */
-    public Class<?>[] getExceptionTypes() {
-        if (exceptionTypes == null) {
-            return EmptyArray.CLASS;
-        }
-        return exceptionTypes.clone();
-    }
-
-    /**
-     * Returns the modifiers for this constructor. The {@link Modifier} class
-     * should be used to decode the result.
-     *
-     * @return the modifiers for this constructor
-     *
-     * @see Modifier
-     */
-    public int getModifiers() {
-        return Method.getMethodModifiers(declaringClass, slot);
-    }
-
-    /**
-     * Returns the name of this constructor.
-     *
-     * @return the name of this constructor
-     */
-    public String getName() {
-        return declaringClass.getName();
-    }
-
-    /**
-     * Returns an array of the {@code Class} objects associated with the
-     * parameter types of this constructor. If the constructor was declared with
-     * no parameters, an empty array will be returned.
-     *
-     * @return the parameter types
-     */
-    public Class<?>[] getParameterTypes() {
-        return parameterTypes.clone();
-    }
-
-    /**
-     * Returns the constructor's signature in non-printable form. This is called
-     * (only) from IO native code and needed for deriving the serialVersionUID
-     * of the class
-     *
-     * @return the constructor's signature
-     */
-    @SuppressWarnings("unused")
-    private String getSignature() {
-        StringBuilder result = new StringBuilder();
-
-        result.append('(');
-        for (int i = 0; i < parameterTypes.length; i++) {
-            result.append(getSignature(parameterTypes[i]));
-        }
-        result.append(")V");
-
-        return result.toString();
-    }
-
-    /**
-     * Returns an integer hash code for this constructor. Constructors which are
-     * equal return the same value for this method. The hash code for a
-     * Constructor is the hash code of the name of the declaring class.
-     *
-     * @return the hash code
-     *
-     * @see #equals
-     */
-    @Override
-    public int hashCode() {
-        return declaringClass.getName().hashCode();
-    }
-
-    /**
-     * Returns a new instance of the declaring class, initialized by dynamically
-     * invoking the constructor represented by this {@code Constructor} object.
-     * This reproduces the effect of {@code new declaringClass(arg1, arg2, ... ,
-     * argN)} This method performs the following:
-     * <ul>
-     * <li>A new instance of the declaring class is created. If the declaring
-     * class cannot be instantiated (i.e. abstract class, an interface, an array
-     * type, or a primitive type) then an InstantiationException is thrown.</li>
-     * <li>If this Constructor object is enforcing access control (see
-     * {@link AccessibleObject}) and this constructor is not accessible from the
-     * current context, an IllegalAccessException is thrown.</li>
-     * <li>If the number of arguments passed and the number of parameters do not
-     * match, an IllegalArgumentException is thrown.</li>
-     * <li>For each argument passed:
-     * <ul>
-     * <li>If the corresponding parameter type is a primitive type, the argument
-     * is unboxed. If the unboxing fails, an IllegalArgumentException is
-     * thrown.</li>
-     * <li>If the resulting argument cannot be converted to the parameter type
-     * via a widening conversion, an IllegalArgumentException is thrown.</li>
-     * </ul>
-     * <li>The constructor represented by this {@code Constructor} object is
-     * then invoked. If an exception is thrown during the invocation, it is
-     * caught and wrapped in an InvocationTargetException. This exception is
-     * then thrown. If the invocation completes normally, the newly initialized
-     * object is returned.
-     * </ul>
-     *
-     * @param args
-     *            the arguments to the constructor
-     *
-     * @return the new, initialized, object
-     *
-     * @throws InstantiationException
-     *                if the class cannot be instantiated
-     * @throws IllegalAccessException
-     *                if this constructor is not accessible
-     * @throws IllegalArgumentException
-     *                if an incorrect number of arguments are passed, or an
-     *                argument could not be converted by a widening conversion
-     * @throws InvocationTargetException
-     *                if an exception was thrown by the invoked constructor
-     *
-     * @see AccessibleObject
-     */
-    public T newInstance(Object... args) throws InstantiationException, IllegalAccessException,
-            IllegalArgumentException, InvocationTargetException {
-        return constructNative (args, declaringClass, parameterTypes, slot, flag);
-    }
-
-    private native T constructNative(Object[] args, Class<T> declaringClass,
-            Class<?>[] parameterTypes, int slot,
-            boolean noAccessCheck) throws InstantiationException, IllegalAccessException,
-            InvocationTargetException;
-
-    /**
-     * Returns a string containing a concise, human-readable description of this
-     * constructor. The format of the string is:
-     *
-     * <ol>
-     *   <li>modifiers (if any)
-     *   <li>declaring class name
-     *   <li>'('
-     *   <li>parameter types, separated by ',' (if any)
-     *   <li>')'
-     *   <li>'throws' plus exception types, separated by ',' (if any)
-     * </ol>
-     *
-     * For example:
-     * {@code public String(byte[],String) throws UnsupportedEncodingException}
-     *
-     * @return a printable representation for this constructor
-     */
-    @Override
-    public String toString() {
-        StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
-
-        if (result.length() != 0)
-            result.append(' ');
-        result.append(declaringClass.getName());
-        result.append("(");
-        result.append(toString(parameterTypes));
-        result.append(")");
-        if (exceptionTypes != null && exceptionTypes.length != 0) {
-            result.append(" throws ");
-            result.append(toString(exceptionTypes));
-        }
-
-        return result.toString();
-    }
-}
diff --git a/libdvm/src/main/java/java/lang/reflect/Field.java b/libdvm/src/main/java/java/lang/reflect/Field.java
deleted file mode 100644
index fa8e5e7..0000000
--- a/libdvm/src/main/java/java/lang/reflect/Field.java
+++ /dev/null
@@ -1,931 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.reflect;
-
-import java.lang.annotation.Annotation;
-import java.util.Comparator;
-import org.apache.harmony.kernel.vm.StringUtils;
-import libcore.reflect.GenericSignatureParser;
-import libcore.reflect.Types;
-
-/**
- * This class represents a field. Information about the field can be accessed,
- * and the field's value can be accessed dynamically.
- */
-public final class Field extends AccessibleObject implements Member {
-
-    /**
-     * Orders fields by their name and declaring class.
-     *
-     * @hide
-     */
-    public static final Comparator<Field> ORDER_BY_NAME_AND_DECLARING_CLASS
-            = new Comparator<Field>() {
-        @Override public int compare(Field a, Field b) {
-            int comparison = a.name.compareTo(b.name);
-            if (comparison != 0) {
-                return comparison;
-            }
-
-            return a.getDeclaringClass().getName().compareTo(b.getDeclaringClass().getName());
-        }
-    };
-
-    private Class<?> declaringClass;
-
-    private Class<?> type;
-
-    private Type genericType;
-
-    private volatile boolean genericTypesAreInitialized = false;
-
-    private String name;
-
-    private int slot;
-
-    private final int fieldDexIndex;
-
-    private static final char TYPE_BOOLEAN = 'Z';
-
-    private static final char TYPE_BYTE = 'B';
-
-    private static final char TYPE_CHAR = 'C';
-
-    private static final char TYPE_SHORT = 'S';
-
-    private static final char TYPE_INTEGER = 'I';
-
-    private static final char TYPE_FLOAT = 'F';
-
-    private static final char TYPE_LONG = 'J';
-
-    private static final char TYPE_DOUBLE = 'D';
-
-    private Field(Class<?> declaringClass, Class<?> type, String name, int slot, int fieldDexIndex) {
-        this.declaringClass = declaringClass;
-        this.type = type;
-        this.name = name;
-        this.slot = slot;
-        this.fieldDexIndex = fieldDexIndex;
-    }
-
-    /**
-     * Returns the index of this field's ID in its dex file.
-     * @hide
-     */
-    public int getDexFieldIndex() {
-        return fieldDexIndex;
-    }
-
-    private synchronized void initGenericType() {
-        if (!genericTypesAreInitialized) {
-            String signatureAttribute = getSignatureAttribute();
-            GenericSignatureParser parser = new GenericSignatureParser(
-                    declaringClass.getClassLoader());
-            parser.parseForField(this.declaringClass, signatureAttribute);
-            genericType = parser.fieldType;
-            if (genericType == null) {
-                genericType = getType();
-            }
-            genericTypesAreInitialized = true;
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    /* package */String getSignatureAttribute() {
-        Object[] annotation = getSignatureAnnotation(declaringClass, slot);
-
-        if (annotation == null) {
-            return null;
-        }
-
-        return StringUtils.combineStrings(annotation);
-    }
-
-    /**
-     * Get the Signature annotation for this field. Returns null if not found.
-     */
-    native private Object[] getSignatureAnnotation(Class declaringClass, int slot);
-
-    /**
-     * Indicates whether or not this field is synthetic.
-     *
-     * @return {@code true} if this field is synthetic, {@code false} otherwise
-     */
-    public boolean isSynthetic() {
-        int flags = getFieldModifiers(declaringClass, slot);
-        return (flags & Modifier.SYNTHETIC) != 0;
-    }
-
-    /**
-     * Returns the string representation of this field, including the field's
-     * generic type.
-     *
-     * @return the string representation of this field
-     */
-    public String toGenericString() {
-        StringBuilder sb = new StringBuilder(80);
-        // append modifiers if any
-        int modifier = getModifiers();
-        if (modifier != 0) {
-            sb.append(Modifier.toString(modifier)).append(' ');
-        }
-        // append generic type
-        appendGenericType(sb, getGenericType());
-        sb.append(' ');
-        // append full field name
-        sb.append(getDeclaringClass().getName()).append('.').append(getName());
-        return sb.toString();
-    }
-
-    /**
-     * Indicates whether or not this field is an enumeration constant.
-     *
-     * @return {@code true} if this field is an enumeration constant, {@code
-     *         false} otherwise
-     */
-    public boolean isEnumConstant() {
-        int flags = getFieldModifiers(declaringClass, slot);
-        return (flags & Modifier.ENUM) != 0;
-    }
-
-    /**
-     * Returns the generic type of this field.
-     *
-     * @return the generic type
-     * @throws GenericSignatureFormatError
-     *             if the generic field signature is invalid
-     * @throws TypeNotPresentException
-     *             if the generic type points to a missing type
-     * @throws MalformedParameterizedTypeException
-     *             if the generic type points to a type that cannot be
-     *             instantiated for some reason
-     */
-    public Type getGenericType() {
-        initGenericType();
-        return Types.getType(genericType);
-    }
-
-    @Override public Annotation[] getDeclaredAnnotations() {
-        return getDeclaredAnnotations(declaringClass, slot);
-    }
-    private static native Annotation[] getDeclaredAnnotations(Class declaringClass, int slot);
-
-    @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-        return getAnnotation(declaringClass, slot, annotationType);
-    }
-    private static native <A extends Annotation> A getAnnotation(
-            Class<?> declaringClass, int slot, Class<A> annotationType);
-
-    @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-        return isAnnotationPresent(declaringClass, slot, annotationType);
-    }
-    private static native boolean isAnnotationPresent(
-            Class<?> declaringClass, int slot, Class<? extends Annotation> annotationType);
-
-    /**
-     * Indicates whether or not the specified {@code object} is equal to this
-     * field. To be equal, the specified object must be an instance of
-     * {@code Field} with the same declaring class, type and name as this field.
-     *
-     * @param object
-     *            the object to compare
-     * @return {@code true} if the specified object is equal to this method,
-     *         {@code false} otherwise
-     * @see #hashCode
-     */
-    @Override
-    public boolean equals(Object object) {
-        return object instanceof Field && toString().equals(object.toString());
-    }
-
-    /**
-     * Returns the value of the field in the specified object. This reproduces
-     * the effect of {@code object.fieldName}
-     *
-     * <p>If the type of this field is a primitive type, the field value is
-     * automatically boxed.
-     *
-     * <p>If this field is static, the object argument is ignored.
-     * Otherwise, if the object is null, a NullPointerException is thrown. If
-     * the object is not an instance of the declaring class of the method, an
-     * IllegalArgumentException is thrown.
-     *
-     * <p>If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @return the field value, possibly boxed
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public Object get(Object object) throws IllegalAccessException, IllegalArgumentException {
-        return getField(object, declaringClass, type, slot, flag);
-    }
-
-    /**
-     * Returns the value of the field in the specified object as a {@code
-     * boolean}. This reproduces the effect of {@code object.fieldName}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @return the field value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public boolean getBoolean(Object object) throws IllegalAccessException,
-            IllegalArgumentException {
-        return getZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN);
-    }
-
-    /**
-     * Returns the value of the field in the specified object as a {@code byte}.
-     * This reproduces the effect of {@code object.fieldName}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @return the field value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public byte getByte(Object object) throws IllegalAccessException, IllegalArgumentException {
-        return getBField(object, declaringClass, type, slot, flag, TYPE_BYTE);
-    }
-
-    /**
-     * Returns the value of the field in the specified object as a {@code char}.
-     * This reproduces the effect of {@code object.fieldName}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @return the field value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public char getChar(Object object) throws IllegalAccessException, IllegalArgumentException {
-        return getCField(object, declaringClass, type, slot, flag, TYPE_CHAR);
-    }
-
-    /**
-     * Returns the class that declares this field.
-     *
-     * @return the declaring class
-     */
-    public Class<?> getDeclaringClass() {
-        return declaringClass;
-    }
-
-    /**
-     * Returns the value of the field in the specified object as a {@code
-     * double}. This reproduces the effect of {@code object.fieldName}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @return the field value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public double getDouble(Object object) throws IllegalAccessException, IllegalArgumentException {
-        return getDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE);
-    }
-
-    /**
-     * Returns the value of the field in the specified object as a {@code float}
-     * . This reproduces the effect of {@code object.fieldName}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @return the field value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public float getFloat(Object object) throws IllegalAccessException, IllegalArgumentException {
-        return getFField(object, declaringClass, type, slot, flag, TYPE_FLOAT);
-    }
-
-    /**
-     * Returns the value of the field in the specified object as an {@code int}.
-     * This reproduces the effect of {@code object.fieldName}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @return the field value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public int getInt(Object object) throws IllegalAccessException, IllegalArgumentException {
-        return getIField(object, declaringClass, type, slot, flag, TYPE_INTEGER);
-    }
-
-    /**
-     * Returns the value of the field in the specified object as a {@code long}.
-     * This reproduces the effect of {@code object.fieldName}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @return the field value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public long getLong(Object object) throws IllegalAccessException, IllegalArgumentException {
-        return getJField(object, declaringClass, type, slot, flag, TYPE_LONG);
-    }
-
-    /**
-     * Returns the modifiers for this field. The {@link Modifier} class should
-     * be used to decode the result.
-     *
-     * @return the modifiers for this field
-     * @see Modifier
-     */
-    public int getModifiers() {
-        return getFieldModifiers(declaringClass, slot);
-    }
-
-    private native int getFieldModifiers(Class<?> declaringClass, int slot);
-
-    /**
-     * Returns the name of this field.
-     *
-     * @return the name of this field
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Returns the value of the field in the specified object as a {@code short}
-     * . This reproduces the effect of {@code object.fieldName}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @return the field value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public short getShort(Object object) throws IllegalAccessException, IllegalArgumentException {
-        return getSField(object, declaringClass, type, slot, flag, TYPE_SHORT);
-    }
-
-    /**
-     * Returns the constructor's signature in non-printable form. This is called
-     * (only) from IO native code and needed for deriving the serialVersionUID
-     * of the class
-     *
-     * @return the constructor's signature.
-     */
-    @SuppressWarnings("unused")
-    private String getSignature() {
-        return getSignature(type);
-    }
-
-    /**
-     * Return the {@link Class} associated with the type of this field.
-     *
-     * @return the type of this field
-     */
-    public Class<?> getType() {
-        return type;
-    }
-
-    /**
-     * Returns an integer hash code for this field. Objects which are equal
-     * return the same value for this method.
-     * <p>
-     * The hash code for a Field is the exclusive-or combination of the hash
-     * code of the field's name and the hash code of the name of its declaring
-     * class.
-     *
-     * @return the hash code for this field
-     * @see #equals
-     */
-    @Override
-    public int hashCode() {
-        return name.hashCode() ^ getDeclaringClass().getName().hashCode();
-    }
-
-    /**
-     * Sets the value of the field in the specified object to the value. This
-     * reproduces the effect of {@code object.fieldName = value}
-     *
-     * <p>If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     *
-     * <p>If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     *
-     * <p>If the field type is a primitive type, the value is automatically
-     * unboxed. If the unboxing fails, an IllegalArgumentException is thrown. If
-     * the value cannot be converted to the field type via a widening
-     * conversion, an IllegalArgumentException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @param value
-     *            the new value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public void set(Object object, Object value) throws IllegalAccessException,
-            IllegalArgumentException {
-        setField(object, declaringClass, type, slot, flag, value);
-    }
-
-    /**
-     * Sets the value of the field in the specified object to the {@code
-     * boolean} value. This reproduces the effect of {@code object.fieldName =
-     * value}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     * <p>
-     * If the value cannot be converted to the field type via a widening
-     * conversion, an IllegalArgumentException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @param value
-     *            the new value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public void setBoolean(Object object, boolean value) throws IllegalAccessException,
-            IllegalArgumentException {
-        setZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN, value);
-    }
-
-    /**
-     * Sets the value of the field in the specified object to the {@code byte}
-     * value. This reproduces the effect of {@code object.fieldName = value}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     * <p>
-     * If the value cannot be converted to the field type via a widening
-     * conversion, an IllegalArgumentException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @param value
-     *            the new value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public void setByte(Object object, byte value) throws IllegalAccessException,
-            IllegalArgumentException {
-        setBField(object, declaringClass, type, slot, flag, TYPE_BYTE, value);
-    }
-
-    /**
-     * Sets the value of the field in the specified object to the {@code char}
-     * value. This reproduces the effect of {@code object.fieldName = value}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     * <p>
-     * If the value cannot be converted to the field type via a widening
-     * conversion, an IllegalArgumentException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @param value
-     *            the new value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public void setChar(Object object, char value) throws IllegalAccessException,
-            IllegalArgumentException {
-        setCField(object, declaringClass, type, slot, flag, TYPE_CHAR, value);
-    }
-
-    /**
-     * Sets the value of the field in the specified object to the {@code double}
-     * value. This reproduces the effect of {@code object.fieldName = value}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     * <p>
-     * If the value cannot be converted to the field type via a widening
-     * conversion, an IllegalArgumentException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @param value
-     *            the new value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public void setDouble(Object object, double value) throws IllegalAccessException,
-            IllegalArgumentException {
-        setDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE, value);
-    }
-
-    /**
-     * Sets the value of the field in the specified object to the {@code float}
-     * value. This reproduces the effect of {@code object.fieldName = value}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     * <p>
-     * If the value cannot be converted to the field type via a widening
-     * conversion, an IllegalArgumentException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @param value
-     *            the new value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public void setFloat(Object object, float value) throws IllegalAccessException,
-            IllegalArgumentException {
-        setFField(object, declaringClass, type, slot, flag, TYPE_FLOAT, value);
-    }
-
-    /**
-     * Set the value of the field in the specified object to the {@code int}
-     * value. This reproduces the effect of {@code object.fieldName = value}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     * <p>
-     * If the value cannot be converted to the field type via a widening
-     * conversion, an IllegalArgumentException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @param value
-     *            the new value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public void setInt(Object object, int value) throws IllegalAccessException,
-            IllegalArgumentException {
-        setIField(object, declaringClass, type, slot, flag, TYPE_INTEGER, value);
-    }
-
-    /**
-     * Sets the value of the field in the specified object to the {@code long}
-     * value. This reproduces the effect of {@code object.fieldName = value}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     * <p>
-     * If the value cannot be converted to the field type via a widening
-     * conversion, an IllegalArgumentException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @param value
-     *            the new value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public void setLong(Object object, long value) throws IllegalAccessException,
-            IllegalArgumentException {
-        setJField(object, declaringClass, type, slot, flag, TYPE_LONG, value);
-    }
-
-    /**
-     * Sets the value of the field in the specified object to the {@code short}
-     * value. This reproduces the effect of {@code object.fieldName = value}
-     * <p>
-     * If this field is static, the object argument is ignored.
-     * Otherwise, if the object is {@code null}, a NullPointerException is
-     * thrown. If the object is not an instance of the declaring class of the
-     * method, an IllegalArgumentException is thrown.
-     * <p>
-     * If this Field object is enforcing access control (see AccessibleObject)
-     * and this field is not accessible from the current context, an
-     * IllegalAccessException is thrown.
-     * <p>
-     * If the value cannot be converted to the field type via a widening
-     * conversion, an IllegalArgumentException is thrown.
-     *
-     * @param object
-     *            the object to access
-     * @param value
-     *            the new value
-     * @throws NullPointerException
-     *             if the object is {@code null} and the field is non-static
-     * @throws IllegalArgumentException
-     *             if the object is not compatible with the declaring class
-     * @throws IllegalAccessException
-     *             if this field is not accessible
-     */
-    public void setShort(Object object, short value) throws IllegalAccessException,
-            IllegalArgumentException {
-        setSField(object, declaringClass, type, slot, flag, TYPE_SHORT, value);
-    }
-
-    /**
-     * Returns a string containing a concise, human-readable description of this
-     * field.
-     * <p>
-     * The format of the string is:
-     * <ol>
-     *   <li>modifiers (if any)
-     *   <li>type
-     *   <li>declaring class name
-     *   <li>'.'
-     *   <li>field name
-     * </ol>
-     * <p>
-     * For example: {@code public static java.io.InputStream
-     * java.lang.System.in}
-     *
-     * @return a printable representation for this field
-     */
-    @Override
-    public String toString() {
-        StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
-        if (result.length() != 0) {
-            result.append(' ');
-        }
-        appendTypeName(result, type);
-        result.append(' ');
-        appendTypeName(result, declaringClass);
-        result.append('.');
-        result.append(name);
-        return result.toString();
-    }
-
-    private native Object getField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck) throws IllegalAccessException;
-
-    private native double getDField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
-    private native int getIField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
-    private native long getJField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
-    private native boolean getZField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
-    private native float getFField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
-    private native char getCField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
-    private native short getSField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
-    private native byte getBField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
-    private native void setField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, Object value) throws IllegalAccessException;
-
-    private native void setDField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor, double v) throws IllegalAccessException;
-
-    private native void setIField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor, int i) throws IllegalAccessException;
-
-    private native void setJField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor, long j) throws IllegalAccessException;
-
-    private native void setZField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor, boolean z) throws IllegalAccessException;
-
-    private native void setFField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor, float f) throws IllegalAccessException;
-
-    private native void setCField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor, char c) throws IllegalAccessException;
-
-    private native void setSField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor, short s) throws IllegalAccessException;
-
-    private native void setBField(Object o, Class<?> declaringClass, Class<?> type, int slot,
-            boolean noAccessCheck, char descriptor, byte b) throws IllegalAccessException;
-
-}
diff --git a/libdvm/src/main/java/java/lang/reflect/Method.java b/libdvm/src/main/java/java/lang/reflect/Method.java
deleted file mode 100644
index f8efbf4..0000000
--- a/libdvm/src/main/java/java/lang/reflect/Method.java
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.reflect;
-
-import java.lang.annotation.Annotation;
-import java.util.Arrays;
-import java.util.Comparator;
-import libcore.util.EmptyArray;
-import org.apache.harmony.kernel.vm.StringUtils;
-import libcore.reflect.GenericSignatureParser;
-import libcore.reflect.ListOfTypes;
-import libcore.reflect.Types;
-
-/**
- * This class represents a method. Information about the method can be accessed,
- * and the method can be invoked dynamically.
- */
-public final class Method extends AccessibleObject implements GenericDeclaration, Member {
-
-    /**
-     * Orders methods by their name, parameters and return type.
-     *
-     * @hide
-     */
-    public static final Comparator<Method> ORDER_BY_SIGNATURE = new Comparator<Method>() {
-        public int compare(Method a, Method b) {
-            int comparison = a.name.compareTo(b.name);
-            if (comparison != 0) {
-                return comparison;
-            }
-
-            Class<?>[] aParameters = a.parameterTypes;
-            Class<?>[] bParameters = b.parameterTypes;
-            int length = Math.min(aParameters.length, bParameters.length);
-            for (int i = 0; i < length; i++) {
-                comparison = aParameters[i].getName().compareTo(bParameters[i].getName());
-                if (comparison != 0) {
-                    return comparison;
-                }
-            }
-
-            if (aParameters.length != bParameters.length) {
-                return aParameters.length - bParameters.length;
-            }
-
-            // this is necessary for methods that have covariant return types.
-            return a.getReturnType().getName().compareTo(b.getReturnType().getName());
-        }
-    };
-
-    private int slot;
-
-    private final int methodDexIndex;
-
-    private Class<?> declaringClass;
-
-    private String name;
-
-    private Class<?>[] parameterTypes;
-
-    private Class<?>[] exceptionTypes;
-
-    private Class<?> returnType;
-
-    private ListOfTypes genericExceptionTypes;
-    private ListOfTypes genericParameterTypes;
-    private Type genericReturnType;
-    private TypeVariable<Method>[] formalTypeParameters;
-    private volatile boolean genericTypesAreInitialized = false;
-
-    private synchronized void initGenericTypes() {
-        if (!genericTypesAreInitialized) {
-            String signatureAttribute = getSignatureAttribute();
-            GenericSignatureParser parser = new GenericSignatureParser(
-                    declaringClass.getClassLoader());
-            parser.parseForMethod(this, signatureAttribute, exceptionTypes);
-            formalTypeParameters = parser.formalTypeParameters;
-            genericParameterTypes = parser.parameterTypes;
-            genericExceptionTypes = parser.exceptionTypes;
-            genericReturnType = parser.returnType;
-            genericTypesAreInitialized = true;
-        }
-    }
-
-    private Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot, int methodDexIndex) {
-        this.declaringClass = declaring;
-        this.name = name;
-        this.slot = slot;
-        this.parameterTypes = paramTypes;
-        this.exceptionTypes = exceptTypes;      // may be null
-        this.returnType = returnType;
-        this.methodDexIndex = methodDexIndex;
-    }
-
-    /** @hide */
-    public int getDexMethodIndex() {
-        return methodDexIndex;
-    }
-
-    public TypeVariable<Method>[] getTypeParameters() {
-        initGenericTypes();
-        return formalTypeParameters.clone();
-    }
-
-    /** {@inheritDoc} */
-    @Override /*package*/ String getSignatureAttribute() {
-        Object[] annotation = getSignatureAnnotation(declaringClass, slot);
-
-        if (annotation == null) {
-            return null;
-        }
-
-        return StringUtils.combineStrings(annotation);
-    }
-
-    /**
-     * Returns the Signature annotation for this method. Returns {@code null} if
-     * not found.
-     */
-    static native Object[] getSignatureAnnotation(Class declaringClass, int slot);
-
-    /**
-     * Returns the string representation of the method's declaration, including
-     * the type parameters.
-     *
-     * @return the string representation of this method
-     */
-    public String toGenericString() {
-        StringBuilder sb = new StringBuilder(80);
-
-        initGenericTypes();
-
-        // append modifiers if any
-        int modifier = getModifiers();
-        if (modifier != 0) {
-            sb.append(Modifier.toString(modifier & ~(Modifier.BRIDGE +
-                    Modifier.VARARGS))).append(' ');
-        }
-        // append type parameters
-        if (formalTypeParameters != null && formalTypeParameters.length > 0) {
-            sb.append('<');
-            for (int i = 0; i < formalTypeParameters.length; i++) {
-                appendGenericType(sb, formalTypeParameters[i]);
-                if (i < formalTypeParameters.length - 1) {
-                    sb.append(",");
-                }
-            }
-            sb.append("> ");
-        }
-        // append return type
-        appendGenericType(sb, Types.getType(genericReturnType));
-        sb.append(' ');
-        // append method name
-        appendTypeName(sb, getDeclaringClass());
-        sb.append(".").append(getName());
-        // append parameters
-        sb.append('(');
-        appendArrayGenericType(sb, Types.getTypeArray(genericParameterTypes, false));
-        sb.append(')');
-        // append exceptions if any
-        Type[] genericExceptionTypeArray = Types.getTypeArray(genericExceptionTypes, false);
-        if (genericExceptionTypeArray.length > 0) {
-            sb.append(" throws ");
-            appendArrayGenericType(sb, genericExceptionTypeArray);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Returns the parameter types as an array of {@code Type} instances, in
-     * declaration order. If this method has no parameters, an empty array is
-     * returned.
-     *
-     * @return the parameter types
-     *
-     * @throws GenericSignatureFormatError
-     *             if the generic method signature is invalid
-     * @throws TypeNotPresentException
-     *             if any parameter type points to a missing type
-     * @throws MalformedParameterizedTypeException
-     *             if any parameter type points to a type that cannot be
-     *             instantiated for some reason
-     */
-    public Type[] getGenericParameterTypes() {
-        initGenericTypes();
-        return Types.getTypeArray(genericParameterTypes, true);
-    }
-
-    /**
-     * Returns the exception types as an array of {@code Type} instances. If
-     * this method has no declared exceptions, an empty array will be returned.
-     *
-     * @return an array of generic exception types
-     *
-     * @throws GenericSignatureFormatError
-     *             if the generic method signature is invalid
-     * @throws TypeNotPresentException
-     *             if any exception type points to a missing type
-     * @throws MalformedParameterizedTypeException
-     *             if any exception type points to a type that cannot be
-     *             instantiated for some reason
-     */
-    public Type[] getGenericExceptionTypes() {
-        initGenericTypes();
-        return Types.getTypeArray(genericExceptionTypes, true);
-    }
-
-    /**
-     * Returns the return type of this method as a {@code Type} instance.
-     *
-     * @return the return type of this method
-     *
-     * @throws GenericSignatureFormatError
-     *             if the generic method signature is invalid
-     * @throws TypeNotPresentException
-     *             if the return type points to a missing type
-     * @throws MalformedParameterizedTypeException
-     *             if the return type points to a type that cannot be
-     *             instantiated for some reason
-     */
-    public Type getGenericReturnType() {
-        initGenericTypes();
-        return Types.getType(genericReturnType);
-    }
-
-    @Override
-    public Annotation[] getDeclaredAnnotations() {
-        return getDeclaredAnnotations(declaringClass, slot);
-    }
-    static native Annotation[] getDeclaredAnnotations(Class<?> declaringClass, int slot);
-
-    @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-        return getAnnotation(declaringClass, slot, annotationType);
-    }
-    static native <A extends Annotation> A getAnnotation(
-            Class<?> declaringClass, int slot, Class<A> annotationType);
-
-    @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
-        if (annotationType == null) {
-            throw new NullPointerException("annotationType == null");
-        }
-        return isAnnotationPresent(declaringClass, slot, annotationType);
-    }
-    static native boolean isAnnotationPresent(
-            Class<?> declaringClass, int slot, Class<? extends Annotation> annotationType);
-
-    private static final Annotation[] NO_ANNOTATIONS = new Annotation[0];
-
-    /**
-     * Creates an array of empty Annotation arrays.
-     */
-    /*package*/ static Annotation[][] noAnnotations(int size) {
-        Annotation[][] annotations = new Annotation[size][];
-        for (int i = 0; i < size; i++) {
-            annotations[i] = NO_ANNOTATIONS;
-        }
-        return annotations;
-    }
-
-    /**
-     * Returns an array of arrays that represent the annotations of the formal
-     * parameters of this method. If there are no parameters on this method,
-     * then an empty array is returned. If there are no annotations set, then
-     * and array of empty arrays is returned.
-     *
-     * @return an array of arrays of {@code Annotation} instances
-     */
-    public Annotation[][] getParameterAnnotations() {
-        Annotation[][] parameterAnnotations
-                = getParameterAnnotations(declaringClass, slot);
-        if (parameterAnnotations.length == 0) {
-            return noAnnotations(parameterTypes.length);
-        }
-        return parameterAnnotations;
-    }
-
-    static native Annotation[][] getParameterAnnotations(Class declaringClass, int slot);
-
-    /**
-     * Indicates whether or not this method takes a variable number argument.
-     *
-     * @return {@code true} if a vararg is declared, {@code false} otherwise
-     */
-    public boolean isVarArgs() {
-        int modifiers = getMethodModifiers(declaringClass, slot);
-        return (modifiers & Modifier.VARARGS) != 0;
-    }
-
-    /**
-     * Indicates whether or not this method is a bridge.
-     *
-     * @return {@code true} if this method is a bridge, {@code false} otherwise
-     */
-    public boolean isBridge() {
-        int modifiers = getMethodModifiers(declaringClass, slot);
-        return (modifiers & Modifier.BRIDGE) != 0;
-    }
-
-    /**
-     * Indicates whether or not this method is synthetic.
-     *
-     * @return {@code true} if this method is synthetic, {@code false} otherwise
-     */
-    public boolean isSynthetic() {
-        int modifiers = getMethodModifiers(declaringClass, slot);
-        return (modifiers & Modifier.SYNTHETIC) != 0;
-    }
-
-    /**
-     * Returns the default value for the annotation member represented by this
-     * method.
-     *
-     * @return the default value, or {@code null} if none
-     *
-     * @throws TypeNotPresentException
-     *             if this annotation member is of type {@code Class} and no
-     *             definition can be found
-     */
-    public Object getDefaultValue() {
-        return getDefaultValue(declaringClass, slot);
-    }
-    native private Object getDefaultValue(Class declaringClass, int slot);
-
-    /**
-     * Indicates whether or not the specified {@code object} is equal to this
-     * method. To be equal, the specified object must be an instance
-     * of {@code Method} with the same declaring class and parameter types
-     * as this method.
-     *
-     * @param object
-     *            the object to compare
-     *
-     * @return {@code true} if the specified object is equal to this
-     *         method, {@code false} otherwise
-     *
-     * @see #hashCode
-     */
-    @Override
-    public boolean equals(Object object) {
-        if (this == object) {
-            return true;
-        }
-        if (!(object instanceof Method)) {
-            return false;
-        }
-        Method rhs = (Method) object;
-        // We don't compare exceptionTypes because two methods
-        // can't differ only by their declared exceptions.
-        return declaringClass.equals(rhs.declaringClass) &&
-            name.equals(rhs.name) &&
-            getModifiers() == rhs.getModifiers() &&
-            returnType.equals(rhs.returnType) &&
-            Arrays.equals(parameterTypes, rhs.parameterTypes);
-    }
-
-    /**
-     * Returns the class that declares this method.
-     *
-     * @return the declaring class
-     */
-    public Class<?> getDeclaringClass() {
-        return declaringClass;
-    }
-
-    /**
-     * Returns the exception types as an array of {@code Class} instances. If
-     * this method has no declared exceptions, an empty array is returned.
-     *
-     * @return the declared exception classes
-     */
-    public Class<?>[] getExceptionTypes() {
-        if (exceptionTypes == null) {
-            return EmptyArray.CLASS;
-        }
-        return exceptionTypes.clone();
-    }
-
-    /**
-     * Returns the modifiers for this method. The {@link Modifier} class should
-     * be used to decode the result.
-     *
-     * @return the modifiers for this method
-     *
-     * @see Modifier
-     */
-    public int getModifiers() {
-        return getMethodModifiers(declaringClass, slot);
-    }
-
-    static native int getMethodModifiers(Class<?> declaringClass, int slot);
-
-    /**
-     * Returns the name of the method represented by this {@code Method}
-     * instance.
-     *
-     * @return the name of this method
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Returns an array of {@code Class} objects associated with the parameter
-     * types of this method. If the method was declared with no parameters, an
-     * empty array will be returned.
-     *
-     * @return the parameter types
-     */
-    public Class<?>[] getParameterTypes() {
-        return parameterTypes.clone();
-    }
-
-    /**
-     * Returns the {@code Class} associated with the return type of this
-     * method.
-     *
-     * @return the return type
-     */
-    public Class<?> getReturnType() {
-        return returnType;
-    }
-
-    /**
-     * Returns an integer hash code for this method. Objects which are equal
-     * return the same value for this method. The hash code for this Method is
-     * the hash code of the name of this method.
-     *
-     * @return hash code for this method
-     *
-     * @see #equals
-     */
-    @Override
-    public int hashCode() {
-        return name.hashCode();
-    }
-
-    /**
-     * Returns the result of dynamically invoking this method. Equivalent to
-     * {@code receiver.methodName(arg1, arg2, ... , argN)}.
-     *
-     * <p>If the method is static, the receiver argument is ignored (and may be null).
-     *
-     * <p>If the method takes no arguments, you can pass {@code (Object[]) null} instead of
-     * allocating an empty array.
-     *
-     * <p>If you're calling a varargs method, you need to pass an {@code Object[]} for the
-     * varargs parameter: that conversion is usually done in {@code javac}, not the VM, and
-     * the reflection machinery does not do this for you. (It couldn't, because it would be
-     * ambiguous.)
-     *
-     * <p>Reflective method invocation follows the usual process for method lookup.
-     *
-     * <p>If an exception is thrown during the invocation it is caught and
-     * wrapped in an InvocationTargetException. This exception is then thrown.
-     *
-     * <p>If the invocation completes normally, the return value itself is
-     * returned. If the method is declared to return a primitive type, the
-     * return value is boxed. If the return type is void, null is returned.
-     *
-     * @param receiver
-     *            the object on which to call this method (or null for static methods)
-     * @param args
-     *            the arguments to the method
-     * @return the result
-     *
-     * @throws NullPointerException
-     *             if {@code receiver == null} for a non-static method
-     * @throws IllegalAccessException
-     *             if this method is not accessible (see {@link AccessibleObject})
-     * @throws IllegalArgumentException
-     *             if the number of arguments doesn't match the number of parameters, the receiver
-     *             is incompatible with the declaring class, or an argument could not be unboxed
-     *             or converted by a widening conversion to the corresponding parameter type
-     * @throws InvocationTargetException
-     *             if an exception was thrown by the invoked method
-     */
-    public Object invoke(Object receiver, Object... args)
-            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
-        if (args == null) {
-            args = EmptyArray.OBJECT;
-        }
-        return invokeNative(receiver, args, declaringClass, parameterTypes, returnType, slot, flag);
-    }
-
-    private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass,
-            Class<?>[] parameterTypes, Class<?> returnType, int slot, boolean noAccessCheck)
-                    throws IllegalAccessException, IllegalArgumentException,
-                            InvocationTargetException;
-
-    /**
-     * Returns a string containing a concise, human-readable description of this
-     * method. The format of the string is:
-     *
-     * <ol>
-     *   <li>modifiers (if any)
-     *   <li>return type or 'void'
-     *   <li>declaring class name
-     *   <li>'('
-     *   <li>parameter types, separated by ',' (if any)
-     *   <li>')'
-     *   <li>'throws' plus exception types, separated by ',' (if any)
-     * </ol>
-     *
-     * For example: {@code public native Object
-     * java.lang.Method.invoke(Object,Object) throws
-     * IllegalAccessException,IllegalArgumentException
-     * ,InvocationTargetException}
-     *
-     * @return a printable representation for this method
-     */
-    @Override
-    public String toString() {
-        StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
-
-        if (result.length() != 0)
-            result.append(' ');
-        result.append(returnType.getName());
-        result.append(' ');
-        result.append(declaringClass.getName());
-        result.append('.');
-        result.append(name);
-        result.append("(");
-        result.append(toString(parameterTypes));
-        result.append(")");
-        if (exceptionTypes != null && exceptionTypes.length != 0) {
-            result.append(" throws ");
-            result.append(toString(exceptionTypes));
-        }
-
-        return result.toString();
-    }
-
-    /**
-     * Returns the constructor's signature in non-printable form. This is called
-     * (only) from IO native code and needed for deriving the serialVersionUID
-     * of the class
-     *
-     * @return The constructor's signature.
-     */
-    @SuppressWarnings("unused")
-    private String getSignature() {
-        StringBuilder result = new StringBuilder();
-
-        result.append('(');
-        for (int i = 0; i < parameterTypes.length; i++) {
-            result.append(getSignature(parameterTypes[i]));
-        }
-        result.append(')');
-        result.append(getSignature(returnType));
-
-        return result.toString();
-    }
-
-}
diff --git a/libdvm/src/main/java/java/lang/reflect/Proxy.java b/libdvm/src/main/java/java/lang/reflect/Proxy.java
deleted file mode 100644
index 3b10887..0000000
--- a/libdvm/src/main/java/java/lang/reflect/Proxy.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-package java.lang.reflect;
-
-import java.io.Serializable;
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-/**
- * {@code Proxy} defines methods for creating dynamic proxy classes and instances.
- * A proxy class implements a declared set of interfaces and delegates method
- * invocations to an {@code InvocationHandler}.
- *
- * @see InvocationHandler
- * @since 1.3
- */
-public class Proxy implements Serializable {
-
-    private static final long serialVersionUID = -2222568056686623797L;
-
-    // maps class loaders to created classes by interface names
-    private static final Map<ClassLoader, Map<String, WeakReference<Class<?>>>> loaderCache = new WeakHashMap<ClassLoader, Map<String, WeakReference<Class<?>>>>();
-
-    // to find previously created types
-    private static final Map<Class<?>, String> proxyCache = new WeakHashMap<Class<?>, String>();
-
-    private static int NextClassNameIndex = 0;
-
-    /**
-     * The invocation handler on which the method calls are dispatched.
-     */
-    protected InvocationHandler h;
-
-    @SuppressWarnings("unused")
-    private Proxy() {
-    }
-
-    /**
-     * Constructs a new {@code Proxy} instance with the specified invocation
-     * handler.
-     *
-     * @param h
-     *            the invocation handler for the newly created proxy
-     */
-    protected Proxy(InvocationHandler h) {
-        this.h = h;
-    }
-
-    /**
-     * Returns the dynamically built {@code Class} for the specified interfaces.
-     * Creates a new {@code Class} when necessary. The order of the interfaces
-     * is relevant. Invocations of this method with the same interfaces but
-     * different order result in different generated classes. The interfaces
-     * must be visible from the supplied class loader; no duplicates are
-     * permitted. All non-public interfaces must be defined in the same package.
-     *
-     * @param loader
-     *            the class loader that will define the proxy class
-     * @param interfaces
-     *            an array of {@code Class} objects, each one identifying an
-     *            interface that will be implemented by the returned proxy
-     *            class
-     * @return a proxy class that implements all of the interfaces referred to
-     *         in the contents of {@code interfaces}
-     * @throws IllegalArgumentException
-     *                if any of the interface restrictions are violated
-     * @throws NullPointerException
-     *                if either {@code interfaces} or any of its elements are
-     *                {@code null}
-     */
-    public static Class<?> getProxyClass(ClassLoader loader,
-            Class<?>... interfaces) throws IllegalArgumentException {
-        // check that interfaces are a valid array of visible interfaces
-        if (interfaces == null) {
-            throw new NullPointerException("interfaces == null");
-        }
-        String commonPackageName = null;
-        for (int i = 0, length = interfaces.length; i < length; i++) {
-            Class<?> next = interfaces[i];
-            if (next == null) {
-                throw new NullPointerException("interfaces[" + i + "] == null");
-            }
-            String name = next.getName();
-            if (!next.isInterface()) {
-                throw new IllegalArgumentException(name + " is not an interface");
-            }
-            if (loader != next.getClassLoader()) {
-                try {
-                    if (next != Class.forName(name, false, loader)) {
-                        throw new IllegalArgumentException(name +
-                                " is not visible from class loader");
-                    }
-                } catch (ClassNotFoundException ex) {
-                    throw new IllegalArgumentException(name + " is not visible from class loader");
-                }
-            }
-            for (int j = i + 1; j < length; j++) {
-                if (next == interfaces[j]) {
-                    throw new IllegalArgumentException(name + " appears more than once");
-                }
-            }
-            if (!Modifier.isPublic(next.getModifiers())) {
-                int last = name.lastIndexOf('.');
-                String p = last == -1 ? "" : name.substring(0, last);
-                if (commonPackageName == null) {
-                    commonPackageName = p;
-                } else if (!commonPackageName.equals(p)) {
-                    throw new IllegalArgumentException("non-public interfaces must be " +
-                            "in the same package");
-                }
-            }
-        }
-
-        // search cache for matching proxy class using the class loader
-        synchronized (loaderCache) {
-            Map<String, WeakReference<Class<?>>> interfaceCache = loaderCache
-                    .get(loader);
-            if (interfaceCache == null) {
-                loaderCache
-                        .put(
-                                loader,
-                                (interfaceCache = new HashMap<String, WeakReference<Class<?>>>()));
-            }
-
-            String interfaceKey = "";
-            if (interfaces.length == 1) {
-                interfaceKey = interfaces[0].getName();
-            } else {
-                StringBuilder names = new StringBuilder();
-                for (int i = 0, length = interfaces.length; i < length; i++) {
-                    names.append(interfaces[i].getName());
-                    names.append(' ');
-                }
-                interfaceKey = names.toString();
-            }
-
-            Class<?> newClass;
-            WeakReference<Class<?>> ref = interfaceCache.get(interfaceKey);
-            if (ref == null) {
-                String nextClassName = "$Proxy" + NextClassNameIndex++;
-                if (commonPackageName != null && commonPackageName.length() > 0) {
-                    nextClassName = commonPackageName + "." + nextClassName;
-                }
-                if (loader == null) {
-                    loader = ClassLoader.getSystemClassLoader();
-                }
-                newClass = generateProxy(nextClassName.replace('.', '/'), interfaces, loader);
-                // Need a weak reference to the class so it can
-                // be unloaded if the class loader is discarded
-                interfaceCache.put(interfaceKey, new WeakReference<Class<?>>(newClass));
-                synchronized (proxyCache) {
-                    // the value is unused
-                    proxyCache.put(newClass, "");
-                }
-            } else {
-                newClass = ref.get();
-                assert newClass != null : "\ninterfaceKey=\"" + interfaceKey + "\""
-                                        + "\nloaderCache=\"" + loaderCache + "\""
-                                        + "\nintfCache=\"" + interfaceCache + "\""
-                                        + "\nproxyCache=\"" + proxyCache + "\"";
-            }
-            return newClass;
-        }
-    }
-
-    /**
-     * Returns an instance of the dynamically built class for the specified
-     * interfaces. Method invocations on the returned instance are forwarded to
-     * the specified invocation handler. The interfaces must be visible from the
-     * supplied class loader; no duplicates are permitted. All non-public
-     * interfaces must be defined in the same package.
-     *
-     * @param loader
-     *            the class loader that will define the proxy class
-     * @param interfaces
-     *            an array of {@code Class} objects, each one identifying an
-     *            interface that will be implemented by the returned proxy
-     *            object
-     * @param h
-     *            the invocation handler that handles the dispatched method
-     *            invocations
-     * @return a new proxy object that delegates to the handler {@code h}
-     * @throws IllegalArgumentException
-     *                if any of the interface restrictions are violated
-     * @throws NullPointerException
-     *                if the interfaces or any of its elements are null
-     */
-    public static Object newProxyInstance(ClassLoader loader,
-            Class<?>[] interfaces, InvocationHandler h)
-            throws IllegalArgumentException {
-        if (h == null) {
-            throw new NullPointerException("h == null");
-        }
-        try {
-            return getProxyClass(loader, interfaces).getConstructor(
-                    new Class<?>[] { InvocationHandler.class }).newInstance(
-                    new Object[] { h });
-        } catch (NoSuchMethodException ex) {
-            throw (InternalError) (new InternalError(ex.toString())
-                    .initCause(ex));
-        } catch (IllegalAccessException ex) {
-            throw (InternalError) (new InternalError(ex.toString())
-                    .initCause(ex));
-        } catch (InstantiationException ex) {
-            throw (InternalError) (new InternalError(ex.toString())
-                    .initCause(ex));
-        } catch (InvocationTargetException ex) {
-            Throwable target = ex.getTargetException();
-            throw (InternalError) (new InternalError(target.toString())
-                    .initCause(target));
-        }
-    }
-
-    /**
-     * Indicates whether or not the specified class is a dynamically generated
-     * proxy class.
-     *
-     * @param cl
-     *            the class
-     * @return {@code true} if the class is a proxy class, {@code false}
-     *         otherwise
-     * @throws NullPointerException
-     *                if the class is {@code null}
-     */
-    public static boolean isProxyClass(Class<?> cl) {
-        if (cl == null) {
-            throw new NullPointerException("cl == null");
-        }
-        synchronized (proxyCache) {
-            return proxyCache.containsKey(cl);
-        }
-    }
-
-    /**
-     * Returns the invocation handler of the specified proxy instance.
-     *
-     * @param proxy
-     *            the proxy instance
-     * @return the invocation handler of the specified proxy instance
-     * @throws IllegalArgumentException
-     *                if the supplied {@code proxy} is not a proxy object
-     */
-    public static InvocationHandler getInvocationHandler(Object proxy)
-            throws IllegalArgumentException {
-
-        if (isProxyClass(proxy.getClass())) {
-            return ((Proxy) proxy).h;
-        }
-
-        throw new IllegalArgumentException("not a proxy instance");
-    }
-
-    native private static Class generateProxy(String name, Class[] interfaces,
-        ClassLoader loader);
-
-    /*
-     * The VM clones this method's descriptor when generating a proxy class.
-     * There is no implementation.
-     */
-    native private static void constructorPrototype(InvocationHandler h);
-}
diff --git a/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java b/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java
deleted file mode 100644
index 01d0e30..0000000
--- a/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.harmony.kernel.vm;
-
-/**
- * String utility functions.
- */
-public final class StringUtils {
-    /**
-     * This class is uninstantiable.
-     */
-    private StringUtils() {
-        // This space intentionally left blank.
-    }
-
-    /**
-     * Combine a list of strings in an <code>Object[]</code> into a single
-     * string.
-     *
-     * @param list non-null; the strings to combine
-     * @return non-null; the combined form
-     */
-    public static String combineStrings(Object[] list) {
-        int listLength = list.length;
-
-        switch (listLength) {
-            case 0: {
-                return "";
-            }
-            case 1: {
-                return (String) list[0];
-            }
-        }
-
-        int strLength = 0;
-
-        for (int i = 0; i < listLength; i++) {
-            strLength += ((String) list[i]).length();
-        }
-
-        StringBuilder sb = new StringBuilder(strLength);
-
-        for (int i = 0; i < listLength; i++) {
-            sb.append(list[i]);
-        }
-
-        return sb.toString();
-    }
-}
diff --git a/libdvm/src/main/java/sun/misc/Unsafe.java b/libdvm/src/main/java/sun/misc/Unsafe.java
deleted file mode 100644
index 884340b..0000000
--- a/libdvm/src/main/java/sun/misc/Unsafe.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package sun.misc;
-
-import dalvik.system.VMStack;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-
-/**
- * The package name notwithstanding, this class is the quasi-standard
- * way for Java code to gain access to and use functionality which,
- * when unsupervised, would allow one to break the pointer/type safety
- * of Java.
- */
-public final class Unsafe {
-    /** Traditional dalvik name. */
-    private static final Unsafe THE_ONE = new Unsafe();
-    /** Traditional RI name. */
-    private static final Unsafe theUnsafe = THE_ONE;
-
-    /**
-     * This class is only privately instantiable.
-     */
-    private Unsafe() {}
-
-    /**
-     * Gets the unique instance of this class. This is only allowed in
-     * very limited situations.
-     */
-    public static Unsafe getUnsafe() {
-        /*
-         * Only code on the bootclasspath is allowed to get at the
-         * Unsafe instance.
-         */
-        ClassLoader calling = VMStack.getCallingClassLoader();
-        if ((calling != null) && (calling != Unsafe.class.getClassLoader())) {
-            throw new SecurityException("Unsafe access denied");
-        }
-
-        return THE_ONE;
-    }
-
-    /**
-     * Gets the raw byte offset from the start of an object's memory to
-     * the memory used to store the indicated instance field.
-     *
-     * @param field non-null; the field in question, which must be an
-     * instance field
-     * @return the offset to the field
-     */
-    public long objectFieldOffset(Field field) {
-        if (Modifier.isStatic(field.getModifiers())) {
-            throw new IllegalArgumentException(
-                    "valid for instance fields only");
-        }
-
-        return objectFieldOffset0(field);
-    }
-
-    /**
-     * Helper for {@link #objectFieldOffset}, which does all the work,
-     * assuming the parameter is deemed valid.
-     *
-     * @param field non-null; the instance field
-     * @return the offset to the field
-     */
-    private static native long objectFieldOffset0(Field field);
-
-    /**
-     * Gets the offset from the start of an array object's memory to
-     * the memory used to store its initial (zeroeth) element.
-     *
-     * @param clazz non-null; class in question; must be an array class
-     * @return the offset to the initial element
-     */
-    public int arrayBaseOffset(Class clazz) {
-        if (! clazz.isArray()) {
-            throw new IllegalArgumentException(
-                    "valid for array classes only");
-        }
-
-        return arrayBaseOffset0(clazz);
-    }
-
-    /**
-     * Helper for {@link #arrayBaseOffset}, which does all the work,
-     * assuming the parameter is deemed valid.
-     *
-     * @return the offset to the field
-     */
-    private static native int arrayBaseOffset0(Class clazz);
-
-    /**
-     * Gets the size of each element of the given array class.
-     *
-     * @param clazz non-null; class in question; must be an array class
-     * @return &gt; 0; the size of each element of the array
-     */
-    public int arrayIndexScale(Class clazz) {
-        if (! clazz.isArray()) {
-            throw new IllegalArgumentException(
-                    "valid for array classes only");
-        }
-
-        return arrayIndexScale0(clazz);
-    }
-
-    /**
-     * Helper for {@link #arrayIndexScale}, which does all the work,
-     * assuming the parameter is deemed valid.
-     *
-     * @return the offset to the field
-     */
-    private static native int arrayIndexScale0(Class clazz);
-
-    /**
-     * Performs a compare-and-set operation on an <code>int</code>
-     * field within the given object.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @param expectedValue expected value of the field
-     * @param newValue new value to store in the field if the contents are
-     * as expected
-     * @return <code>true</code> if the new value was in fact stored, and
-     * <code>false</code> if not
-     */
-    public native boolean compareAndSwapInt(Object obj, long offset,
-            int expectedValue, int newValue);
-
-    /**
-     * Performs a compare-and-set operation on a <code>long</code>
-     * field within the given object.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @param expectedValue expected value of the field
-     * @param newValue new value to store in the field if the contents are
-     * as expected
-     * @return <code>true</code> if the new value was in fact stored, and
-     * <code>false</code> if not
-     */
-    public native boolean compareAndSwapLong(Object obj, long offset,
-            long expectedValue, long newValue);
-
-    /**
-     * Performs a compare-and-set operation on an <code>Object</code>
-     * field (that is, a reference field) within the given object.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @param expectedValue expected value of the field
-     * @param newValue new value to store in the field if the contents are
-     * as expected
-     * @return <code>true</code> if the new value was in fact stored, and
-     * <code>false</code> if not
-     */
-    public native boolean compareAndSwapObject(Object obj, long offset,
-            Object expectedValue, Object newValue);
-
-    /**
-     * Gets an <code>int</code> field from the given object,
-     * using <code>volatile</code> semantics.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @return the retrieved value
-     */
-    public native int getIntVolatile(Object obj, long offset);
-
-    /**
-     * Stores an <code>int</code> field into the given object,
-     * using <code>volatile</code> semantics.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @param newValue the value to store
-     */
-    public native void putIntVolatile(Object obj, long offset, int newValue);
-
-    /**
-     * Gets a <code>long</code> field from the given object,
-     * using <code>volatile</code> semantics.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @return the retrieved value
-     */
-    public native long getLongVolatile(Object obj, long offset);
-
-    /**
-     * Stores a <code>long</code> field into the given object,
-     * using <code>volatile</code> semantics.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @param newValue the value to store
-     */
-    public native void putLongVolatile(Object obj, long offset, long newValue);
-
-    /**
-     * Gets an <code>Object</code> field from the given object,
-     * using <code>volatile</code> semantics.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @return the retrieved value
-     */
-    public native Object getObjectVolatile(Object obj, long offset);
-
-    /**
-     * Stores an <code>Object</code> field into the given object,
-     * using <code>volatile</code> semantics.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @param newValue the value to store
-     */
-    public native void putObjectVolatile(Object obj, long offset,
-            Object newValue);
-
-    /**
-     * Gets an <code>int</code> field from the given object.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @return the retrieved value
-     */
-    public native int getInt(Object obj, long offset);
-
-    /**
-     * Stores an <code>int</code> field into the given object.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @param newValue the value to store
-     */
-    public native void putInt(Object obj, long offset, int newValue);
-
-    /**
-     * Lazy set an int field.
-     */
-    public native void putOrderedInt(Object obj, long offset, int newValue);
-
-    /**
-     * Gets a <code>long</code> field from the given object.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @return the retrieved value
-     */
-    public native long getLong(Object obj, long offset);
-
-    /**
-     * Stores a <code>long</code> field into the given object.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @param newValue the value to store
-     */
-    public native void putLong(Object obj, long offset, long newValue);
-
-    /**
-     * Lazy set a long field.
-     */
-    public native void putOrderedLong(Object obj, long offset, long newValue);
-
-    /**
-     * Gets an <code>Object</code> field from the given object.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @return the retrieved value
-     */
-    public native Object getObject(Object obj, long offset);
-
-    /**
-     * Stores an <code>Object</code> field into the given object.
-     *
-     * @param obj non-null; object containing the field
-     * @param offset offset to the field within <code>obj</code>
-     * @param newValue the value to store
-     */
-    public native void putObject(Object obj, long offset, Object newValue);
-
-    /**
-     * Lazy set an object field.
-     */
-    public native void putOrderedObject(Object obj, long offset,
-            Object newValue);
-
-    /**
-     * Parks the calling thread for the specified amount of time,
-     * unless the "permit" for the thread is already available (due to
-     * a previous call to {@link #unpark}. This method may also return
-     * spuriously (that is, without the thread being told to unpark
-     * and without the indicated amount of time elapsing).
-     *
-     * <p>See {@link java.util.concurrent.locks.LockSupport} for more
-     * in-depth information of the behavior of this method.</p>
-     *
-     * @param absolute whether the given time value is absolute
-     * milliseconds-since-the-epoch (<code>true</code>) or relative
-     * nanoseconds-from-now (<code>false</code>)
-     * @param time the (absolute millis or relative nanos) time value
-     */
-    public void park(boolean absolute, long time) {
-        if (absolute) {
-            Thread.currentThread().parkUntil(time);
-        } else {
-            Thread.currentThread().parkFor(time);
-        }
-    }
-
-    /**
-     * Unparks the given object, which must be a {@link Thread}.
-     *
-     * <p>See {@link java.util.concurrent.locks.LockSupport} for more
-     * in-depth information of the behavior of this method.</p>
-     *
-     * @param obj non-null; the object to unpark
-     */
-    public void unpark(Object obj) {
-        if (obj instanceof Thread) {
-            ((Thread) obj).unpark();
-        } else {
-            throw new IllegalArgumentException("valid for Threads only");
-        }
-    }
-
-    /**
-     * Allocates an instance of the given class without running the constructor.
-     * The class' <clinit> will be run, if necessary.
-     */
-    public native Object allocateInstance(Class<?> c);
-}
diff --git a/luni/src/main/java/java/lang/CaseMapper.java b/luni/src/main/java/java/lang/CaseMapper.java
index 4e411d1..1da621c 100644
--- a/luni/src/main/java/java/lang/CaseMapper.java
+++ b/luni/src/main/java/java/lang/CaseMapper.java
@@ -49,7 +49,7 @@
         // Note that Greek isn't a particularly hard case for toLowerCase, only toUpperCase.
         String languageCode = locale.getLanguage();
         if (languageCode.equals("tr") || languageCode.equals("az") || languageCode.equals("lt")) {
-            return ICU.toLowerCase(s, locale.toString());
+            return ICU.toLowerCase(s, locale);
         }
 
         char[] newValue = null;
@@ -59,7 +59,7 @@
             char newCh;
             if (ch == LATIN_CAPITAL_I_WITH_DOT || Character.isHighSurrogate(ch)) {
                 // Punt these hard cases.
-                return ICU.toLowerCase(s, locale.toString());
+                return ICU.toLowerCase(s, locale);
             } else if (ch == GREEK_CAPITAL_SIGMA && isFinalSigma(value, offset, count, i)) {
                 newCh = GREEK_SMALL_FINAL_SIGMA;
             } else {
@@ -150,7 +150,7 @@
     public static String toUpperCase(Locale locale, String s, char[] value, int offset, int count) {
         String languageCode = locale.getLanguage();
         if (languageCode.equals("tr") || languageCode.equals("az") || languageCode.equals("lt")) {
-            return ICU.toUpperCase(s, locale.toString());
+            return ICU.toUpperCase(s, locale);
         }
         if (languageCode.equals("el")) {
             return EL_UPPER.get().transliterate(s);
@@ -161,7 +161,7 @@
         for (int o = offset, end = offset + count; o < end; o++) {
             char ch = value[o];
             if (Character.isHighSurrogate(ch)) {
-                return ICU.toUpperCase(s, locale.toString());
+                return ICU.toUpperCase(s, locale);
             }
             int index = upperIndex(ch);
             if (index == -1) {
diff --git a/luni/src/main/java/java/lang/Runtime.java b/luni/src/main/java/java/lang/Runtime.java
index 4b66c2d..a3cb83e 100644
--- a/luni/src/main/java/java/lang/Runtime.java
+++ b/luni/src/main/java/java/lang/Runtime.java
@@ -307,57 +307,64 @@
     }
 
     /**
-     * Loads and links the dynamic library that is identified through the
-     * specified path. This method is similar to {@link #loadLibrary(String)},
-     * but it accepts a full path specification whereas {@code loadLibrary} just
-     * accepts the name of the library to load.
+     * Loads the shared library found at the given absolute path.
+     * This should be of the form {@code /path/to/library/libMyLibrary.so}.
+     * Most callers should use {@link #loadLibrary(String)} instead, and
+     * let the system find the correct file to load.
      *
-     * @param pathName
-     *            the absolute (platform dependent) path to the library to load.
-     * @throws UnsatisfiedLinkError
-     *             if the library can not be loaded.
+     * @throws UnsatisfiedLinkError if the library can not be loaded,
+     * either because it's not found or because there is something wrong with it.
      */
-    public void load(String pathName) {
-        load(pathName, VMStack.getCallingClassLoader());
+    public void load(String absolutePath) {
+        load(absolutePath, VMStack.getCallingClassLoader());
     }
 
     /*
-     * Loads and links the given library without security checks.
+     * Loads the given shared library using the given ClassLoader.
      */
-    void load(String pathName, ClassLoader loader) {
-        if (pathName == null) {
-            throw new NullPointerException("pathName == null");
+    void load(String absolutePath, ClassLoader loader) {
+        if (absolutePath == null) {
+            throw new NullPointerException("absolutePath == null");
         }
-        String error = doLoad(pathName, loader);
+        String error = doLoad(absolutePath, loader);
         if (error != null) {
             throw new UnsatisfiedLinkError(error);
         }
     }
 
     /**
-     * Loads and links the library with the specified name. The mapping of the
-     * specified library name to the full path for loading the library is
-     * implementation-dependent.
+     * Loads a shared library. Class loaders have some influence over this
+     * process, but for a typical Android app, it works as follows:
      *
-     * @param libName
-     *            the name of the library to load.
-     * @throws UnsatisfiedLinkError
-     *             if the library can not be loaded.
+     * <p>Given the name {@code "MyLibrary"}, that string will be passed to
+     * {@link System#mapLibraryName}. That means it would be a mistake
+     * for the caller to include the usual {@code "lib"} prefix and {@code ".so"}
+     * suffix.
+     *
+     * <p>That file will then be searched for on the application's native library
+     * search path. This consists of the application's own native library directory
+     * followed by the system's native library directories.
+     *
+     * @throws UnsatisfiedLinkError if the library can not be loaded,
+     * either because it's not found or because there is something wrong with it.
      */
-    public void loadLibrary(String libName) {
-        loadLibrary(libName, VMStack.getCallingClassLoader());
+    public void loadLibrary(String nickname) {
+        loadLibrary(nickname, VMStack.getCallingClassLoader());
     }
 
     /*
-     * Searches for a library, then loads and links it without security checks.
+     * Searches for and loads the given shared library using the given ClassLoader.
      */
     void loadLibrary(String libraryName, ClassLoader loader) {
         if (loader != null) {
             String filename = loader.findLibrary(libraryName);
             if (filename == null) {
-                throw new UnsatisfiedLinkError("Couldn't load " + libraryName +
-                                               " from loader " + loader +
-                                               ": findLibrary returned null");
+                // It's not necessarily true that the ClassLoader used
+                // System.mapLibraryName, but the default setup does, and it's
+                // misleading to say we didn't find "libMyLibrary.so" when we
+                // actually searched for "liblibMyLibrary.so.so".
+                throw new UnsatisfiedLinkError(loader + " couldn't find \"" +
+                                               System.mapLibraryName(libraryName) + "\"");
             }
             String error = doLoad(filename, loader);
             if (error != null) {
diff --git a/luni/src/main/java/java/lang/System.java b/luni/src/main/java/java/lang/System.java
index 2d33bc6..185701e 100644
--- a/luni/src/main/java/java/lang/System.java
+++ b/luni/src/main/java/java/lang/System.java
@@ -584,27 +584,14 @@
     }
 
     /**
-     * Loads and links the dynamic library that is identified through the
-     * specified path. This method is similar to {@link #loadLibrary(String)},
-     * but it accepts a full path specification whereas {@code loadLibrary} just
-     * accepts the name of the library to load.
-     *
-     * @param pathName
-     *            the path of the file to be loaded.
+     * See {@link Runtime#load}.
      */
     public static void load(String pathName) {
         Runtime.getRuntime().load(pathName, VMStack.getCallingClassLoader());
     }
 
     /**
-     * Loads and links the library with the specified name. The mapping of the
-     * specified library name to the full path for loading the library is
-     * implementation-dependent.
-     *
-     * @param libName
-     *            the name of the library to load.
-     * @throws UnsatisfiedLinkError
-     *             if the library could not be loaded.
+     * See {@link Runtime#loadLibrary}.
      */
     public static void loadLibrary(String libName) {
         Runtime.getRuntime().loadLibrary(libName, VMStack.getCallingClassLoader());
@@ -722,24 +709,15 @@
 
     /**
      * Returns the platform specific file name format for the shared library
-     * named by the argument.
-     *
-     * @param userLibName
-     *            the name of the library to look up.
-     * @return the platform specific filename for the library.
+     * named by the argument. On Android, this would turn {@code "MyLibrary"} into
+     * {@code "libMyLibrary.so"}.
      */
-    public static native String mapLibraryName(String userLibName);
+    public static native String mapLibraryName(String nickname);
 
     /**
-     * Sets the value of the named static field in the receiver to the passed in
-     * argument.
-     *
-     * @param fieldName
-     *            the name of the field to set, one of in, out, or err
-     * @param stream
-     *            the new value of the field
+     * Used to set System.err, System.in, and System.out.
      */
-    private static native void setFieldImpl(String fieldName, String signature, Object stream);
+    private static native void setFieldImpl(String field, String signature, Object stream);
 
     /**
      * A properties class that prohibits changes to any of the properties
diff --git a/luni/src/main/java/java/security/Signature.java b/luni/src/main/java/java/security/Signature.java
index 7dd7d93..a39d59b 100644
--- a/luni/src/main/java/java/security/Signature.java
+++ b/luni/src/main/java/java/security/Signature.java
@@ -703,7 +703,7 @@
 
         @Override
         public Object clone() throws CloneNotSupportedException {
-            SignatureSpi spi = (SignatureSpi) spiImpl.clone();
+            SignatureSpi spi = spiImpl != null ? (SignatureSpi) spiImpl.clone() : null;
             return new SignatureImpl(getAlgorithm(), getProvider(), spi);
         }
 
diff --git a/luni/src/main/java/java/text/BreakIterator.java b/luni/src/main/java/java/text/BreakIterator.java
index b14647c..81545b2 100644
--- a/luni/src/main/java/java/text/BreakIterator.java
+++ b/luni/src/main/java/java/text/BreakIterator.java
@@ -268,13 +268,9 @@
     /**
      * Returns a new instance of {@code BreakIterator} to iterate over
      * characters using the given locale.
-     *
-     * @param where
-     *            the given locale.
-     * @return a new instance of {@code BreakIterator} using the given locale.
      */
-    public static BreakIterator getCharacterInstance(Locale where) {
-        return new RuleBasedBreakIterator(NativeBreakIterator.getCharacterInstance(where));
+    public static BreakIterator getCharacterInstance(Locale locale) {
+        return new RuleBasedBreakIterator(NativeBreakIterator.getCharacterInstance(locale));
     }
 
     /**
@@ -290,14 +286,9 @@
     /**
      * Returns a new instance of {@code BreakIterator} to iterate over
      * line breaks using the given locale.
-     *
-     * @param where
-     *            the given locale.
-     * @return a new instance of {@code BreakIterator} using the given locale.
-     * @throws NullPointerException if {@code where} is {@code null}.
      */
-    public static BreakIterator getLineInstance(Locale where) {
-        return new RuleBasedBreakIterator(NativeBreakIterator.getLineInstance(where));
+    public static BreakIterator getLineInstance(Locale locale) {
+        return new RuleBasedBreakIterator(NativeBreakIterator.getLineInstance(locale));
     }
 
     /**
@@ -313,14 +304,9 @@
     /**
      * Returns a new instance of {@code BreakIterator} to iterate over
      * sentence-breaks using the given locale.
-     *
-     * @param where
-     *            the given locale.
-     * @return a new instance of {@code BreakIterator} using the given locale.
-     * @throws NullPointerException if {@code where} is {@code null}.
      */
-    public static BreakIterator getSentenceInstance(Locale where) {
-        return new RuleBasedBreakIterator(NativeBreakIterator.getSentenceInstance(where));
+    public static BreakIterator getSentenceInstance(Locale locale) {
+        return new RuleBasedBreakIterator(NativeBreakIterator.getSentenceInstance(locale));
     }
 
     /**
@@ -336,14 +322,9 @@
     /**
      * Returns a new instance of {@code BreakIterator} to iterate over
      * word-breaks using the given locale.
-     *
-     * @param where
-     *            the given locale.
-     * @return a new instance of {@code BreakIterator} using the given locale.
-     * @throws NullPointerException if {@code where} is {@code null}.
      */
-    public static BreakIterator getWordInstance(Locale where) {
-        return new RuleBasedBreakIterator(NativeBreakIterator.getWordInstance(where));
+    public static BreakIterator getWordInstance(Locale locale) {
+        return new RuleBasedBreakIterator(NativeBreakIterator.getWordInstance(locale));
     }
 
     /**
diff --git a/luni/src/main/java/java/text/DecimalFormat.java b/luni/src/main/java/java/text/DecimalFormat.java
index fbbc172..dc70886 100644
--- a/luni/src/main/java/java/text/DecimalFormat.java
+++ b/luni/src/main/java/java/text/DecimalFormat.java
@@ -900,8 +900,9 @@
      */
     @Override
     public void setCurrency(Currency currency) {
-        ndf.setCurrency(Currency.getInstance(currency.getCurrencyCode()));
-        symbols.setCurrency(currency);
+        Currency instance = Currency.getInstance(currency.getCurrencyCode());
+        symbols.setCurrency(instance);
+        ndf.setCurrency(symbols.getCurrencySymbol(), currency.getCurrencyCode());
     }
 
     /**
diff --git a/luni/src/main/java/java/util/Currency.java b/luni/src/main/java/java/util/Currency.java
index e8ecdde..11b5af1 100644
--- a/luni/src/main/java/java/util/Currency.java
+++ b/luni/src/main/java/java/util/Currency.java
@@ -35,7 +35,7 @@
 
     private Currency(String currencyCode) {
         this.currencyCode = currencyCode;
-        String symbol = ICU.getCurrencySymbol(Locale.US.toString(), currencyCode);
+        String symbol = ICU.getCurrencySymbol(Locale.US, currencyCode);
         if (symbol == null) {
             throw new IllegalArgumentException("Unsupported ISO 4217 currency code: " +
                     currencyCode);
@@ -123,7 +123,7 @@
      * @since 1.7
      */
     public String getDisplayName(Locale locale) {
-        return ICU.getCurrencyDisplayName(locale.toString(), currencyCode);
+        return ICU.getCurrencyDisplayName(locale, currencyCode);
     }
 
     /**
@@ -157,10 +157,6 @@
      * <p>If there is no locale-specific currency symbol, the ISO 4217 currency code is returned.
      */
     public String getSymbol(Locale locale) {
-        if (locale.getCountry().length() == 0) {
-            return currencyCode;
-        }
-
         // Check the locale first, in case the locale has the same currency.
         LocaleData localeData = LocaleData.get(locale);
         if (localeData.internationalCurrencySymbol.equals(currencyCode)) {
@@ -168,7 +164,7 @@
         }
 
         // Try ICU, and fall back to the currency code if ICU has nothing.
-        String symbol = ICU.getCurrencySymbol(locale.toString(), currencyCode);
+        String symbol = ICU.getCurrencySymbol(locale, currencyCode);
         return symbol != null ? symbol : currencyCode;
     }
 
diff --git a/luni/src/main/java/java/util/Locale.java b/luni/src/main/java/java/util/Locale.java
index 163a627..a3eaf21 100644
--- a/luni/src/main/java/java/util/Locale.java
+++ b/luni/src/main/java/java/util/Locale.java
@@ -340,9 +340,13 @@
          * @throws IllformedLocaleException if the language was invalid.
          */
         public Builder setLanguage(String language) {
+            this.language = normalizeAndValidateLanguage(language);
+            return this;
+        }
+
+        private static String normalizeAndValidateLanguage(String language) {
             if (language == null || language.isEmpty()) {
-                this.language = "";
-                return this;
+                return "";
             }
 
             final String lowercaseLanguage = language.toLowerCase(Locale.ROOT);
@@ -350,8 +354,7 @@
                 throw new IllformedLocaleException("Invalid language: " + language);
             }
 
-            this.language = lowercaseLanguage;
-            return this;
+            return lowercaseLanguage;
         }
 
         /**
@@ -397,9 +400,13 @@
          * @throws IllformedLocaleException if {@code} region is invalid.
          */
         public Builder setRegion(String region) {
+            this.region = normalizeAndValidateRegion(region);
+            return this;
+        }
+
+        private static String normalizeAndValidateRegion(String region) {
             if (region == null || region.isEmpty()) {
-                this.region = "";
-                return this;
+                return "";
             }
 
             final String uppercaseRegion = region.toUpperCase(Locale.ROOT);
@@ -408,8 +415,7 @@
                 throw new IllformedLocaleException("Invalid region: " + region);
             }
 
-            this.region = uppercaseRegion;
-            return this;
+            return uppercaseRegion;
         }
 
         /**
@@ -432,9 +438,13 @@
          * @throws IllformedLocaleException if {@code} variant is invalid.
          */
         public Builder setVariant(String variant) {
+            this.variant = normalizeAndValidateVariant(variant);
+            return this;
+        }
+
+        private static String normalizeAndValidateVariant(String variant) {
             if (variant == null || variant.isEmpty()) {
-                this.variant = "";
-                return this;
+                return "";
             }
 
             // Note that unlike extensions, we canonicalize to lower case alphabets
@@ -461,8 +471,7 @@
             }
 
 
-            this.variant = normalizedVariant;
-            return this;
+            return normalizedVariant;
         }
 
         /**
@@ -766,14 +775,15 @@
             // because the RI allows this builder to reused.
             return new Locale(language, region, variant, script,
                     attributes, keywords, extensions,
-                    false /* from public constructor */);
+                    true /* has validated fields */);
         }
     }
 
     /**
      * Returns a locale for a given BCP-47 language tag. This method is more
      * lenient than {@link Builder#setLanguageTag}. For a given language tag, parsing
-     * will proceed upto the first malformed subtag. All subsequent tags are discarded.
+     * will proceed up to the first malformed subtag. All subsequent tags are discarded.
+     * Note that language tags use {@code -} rather than {@code _}, for example {@code en-US}.
      *
      * @throws NullPointerException if {@code languageTag} is {@code null}.
      *
@@ -793,10 +803,6 @@
     private transient String variantCode;
     private transient String scriptCode;
 
-    private transient String cachedToStringResult;
-    private transient String cachedLanguageTag;
-    private transient String cachedIcuLocaleId;
-
     /* Sorted, Unmodifiable */
     private transient Set<String> unicodeAttributes;
     /* Sorted, Unmodifiable */
@@ -805,13 +811,23 @@
     private transient Map<Character, String> extensions;
 
     /**
+     * Whether this instance was constructed from a builder. We can make
+     * stronger assumptions about the validity of Locale fields if this was
+     * constructed by a builder.
+     */
+    private transient final boolean hasValidatedFields;
+
+    private transient String cachedToStringResult;
+    private transient String cachedLanguageTag;
+    private transient String cachedIcuLocaleId;
+
+    /**
      * There's a circular dependency between toLowerCase/toUpperCase and
      * Locale.US. Work around this by avoiding these methods when constructing
      * the built-in locales.
-     *
-     * @param unused required for this constructor to have a unique signature
      */
-    private Locale(boolean unused, String lowerCaseLanguageCode, String upperCaseCountryCode) {
+    private Locale(boolean hasValidatedFields, String lowerCaseLanguageCode,
+            String upperCaseCountryCode) {
         this.languageCode = lowerCaseLanguageCode;
         this.countryCode = upperCaseCountryCode;
         this.variantCode = "";
@@ -820,6 +836,8 @@
         this.unicodeAttributes = Collections.EMPTY_SET;
         this.unicodeKeywords = Collections.EMPTY_MAP;
         this.extensions = Collections.EMPTY_MAP;
+
+        this.hasValidatedFields = hasValidatedFields;
     }
 
     /**
@@ -827,7 +845,7 @@
      */
     public Locale(String language) {
         this(language, "", "", "", Collections.EMPTY_SET, Collections.EMPTY_MAP,
-                Collections.EMPTY_MAP, true /* from public constructor */);
+                Collections.EMPTY_MAP, false /* has validated fields */);
     }
 
     /**
@@ -835,7 +853,7 @@
      */
     public Locale(String language, String country) {
         this(language, country, "", "", Collections.EMPTY_SET, Collections.EMPTY_MAP,
-                Collections.EMPTY_MAP, true /* from public constructor */);
+                Collections.EMPTY_MAP, false /* has validated fields */);
     }
 
     /**
@@ -847,14 +865,18 @@
             /* nonnull */ Set<String> unicodeAttributes,
             /* nonnull */ Map<String, String> unicodeKeywords,
             /* nonnull */ Map<Character, String> extensions,
-            boolean fromPublicConstructor) {
+            boolean hasValidatedFields) {
         if (language == null || country == null || variant == null) {
             throw new NullPointerException("language=" + language +
                     ",country=" + country +
                     ",variant=" + variant);
         }
 
-        if (fromPublicConstructor) {
+        if (hasValidatedFields) {
+            this.languageCode = adjustLanguageCode(language);
+            this.countryCode = country;
+            this.variantCode = variant;
+        } else {
             if (language.isEmpty() && country.isEmpty()) {
                 languageCode = "";
                 countryCode = "";
@@ -864,36 +886,31 @@
                 countryCode = country.toUpperCase(Locale.US);
                 variantCode = variant;
             }
-        } else {
-            this.languageCode = adjustLanguageCode(language);
-            this.countryCode = country;
-            this.variantCode = variant;
         }
 
         this.scriptCode = scriptCode;
 
-        if (fromPublicConstructor) {
-            this.unicodeAttributes = unicodeAttributes;
-            this.unicodeKeywords = unicodeKeywords;
-            this.extensions = extensions;
-        } else {
+        if (hasValidatedFields) {
             Set<String> attribsCopy = new TreeSet<String>(unicodeAttributes);
-            Map<String, String> keywordsCopy = new TreeMap<String, String>(
-                    unicodeKeywords);
-            Map<Character, String> extensionsCopy = new TreeMap<Character, String>(
-                    extensions);
+            Map<String, String> keywordsCopy = new TreeMap<String, String>(unicodeKeywords);
+            Map<Character, String> extensionsCopy = new TreeMap<Character, String>(extensions);
 
             // We need to transform the list of attributes & keywords set on the
             // builder to a unicode locale extension. i.e, if we have any keywords
             // or attributes set, Locale#getExtension('u') should return a well
             // formed extension.
-            addUnicodeExtensionToExtensionsMap(attribsCopy, keywordsCopy,
-                    extensionsCopy);
+            addUnicodeExtensionToExtensionsMap(attribsCopy, keywordsCopy, extensionsCopy);
 
             this.unicodeAttributes = Collections.unmodifiableSet(attribsCopy);
             this.unicodeKeywords = Collections.unmodifiableMap(keywordsCopy);
             this.extensions = Collections.unmodifiableMap(extensionsCopy);
+        } else {
+            this.unicodeAttributes = unicodeAttributes;
+            this.unicodeKeywords = unicodeKeywords;
+            this.extensions = extensions;
         }
+
+        this.hasValidatedFields = hasValidatedFields;
     }
 
     /**
@@ -903,7 +920,7 @@
     public Locale(String language, String country, String variant) {
         this(language, country, variant, "", Collections.EMPTY_SET,
                 Collections.EMPTY_MAP, Collections.EMPTY_MAP,
-                true /* from public constructor */);
+                false /* has validated fields */);
     }
 
     @Override public Object clone() {
@@ -987,10 +1004,16 @@
         if (countryCode.isEmpty()) {
             return "";
         }
-        String result = ICU.getDisplayCountryNative(getIcuLocaleId(), locale.getIcuLocaleId());
+
+        try {
+            Builder.normalizeAndValidateRegion(countryCode);
+        } catch (IllformedLocaleException ex) {
+            return countryCode;
+        }
+
+        String result = ICU.getDisplayCountry(this, locale);
         if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
-            result = ICU.getDisplayCountryNative(getIcuLocaleId(),
-                    Locale.getDefault().getIcuLocaleId());
+            result = ICU.getDisplayCountry(this, Locale.getDefault());
         }
         return result;
     }
@@ -1011,19 +1034,24 @@
             return "";
         }
 
-        // http://b/8049507 --- frameworks/base should use fil_PH instead of tl_PH.
-        // Until then, we're stuck covering their tracks, making it look like they're
-        // using "fil" when they're not.
-        String localeString = toString();
-        if (languageCode.equals("tl")) {
-            localeString = toNewString("fil", countryCode, variantCode, scriptCode,
-                    extensions);
+        // Hacks for backward compatibility.
+        //
+        // Our language tag will contain "und" if the languageCode is invalid
+        // or missing. ICU will then return "langue indéterminée" or the equivalent
+        // display language for the indeterminate language code.
+        //
+        // Sigh... ugh... and what not.
+        try {
+            Builder.normalizeAndValidateLanguage(languageCode);
+        } catch (IllformedLocaleException ex) {
+            return languageCode;
         }
 
-        String result = ICU.getDisplayLanguageNative(localeString, locale.getIcuLocaleId());
+        // TODO: We need a new hack or a complete fix for http://b/8049507 --- We would
+        // cover the frameworks' tracks when they were using "tl" instead of "fil".
+        String result = ICU.getDisplayLanguage(this, locale);
         if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
-            result = ICU.getDisplayLanguageNative(localeString,
-                    Locale.getDefault().getIcuLocaleId());
+            result = ICU.getDisplayLanguage(this, Locale.getDefault());
         }
         return result;
     }
@@ -1108,13 +1136,27 @@
      * returned.
      */
     public String getDisplayVariant(Locale locale) {
-        if (variantCode.length() == 0) {
+        if (variantCode.isEmpty()) {
+            return "";
+        }
+
+        try {
+            Builder.normalizeAndValidateVariant(variantCode);
+        } catch (IllformedLocaleException ilfe) {
             return variantCode;
         }
-        String result = ICU.getDisplayVariantNative(getIcuLocaleId(), locale.getIcuLocaleId());
+
+        String result = ICU.getDisplayVariant(this, locale);
         if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
-            result = ICU.getDisplayVariantNative(getIcuLocaleId(),
-                    Locale.getDefault().getIcuLocaleId());
+            result = ICU.getDisplayVariant(this, Locale.getDefault());
+        }
+
+        // The "old style" locale constructors allow us to pass in variants that aren't
+        // valid BCP-47 variant subtags. When that happens, toLanguageTag will not emit
+        // them. Note that we know variantCode.length() > 0 due to the isEmpty check at
+        // the beginning of this function.
+        if (result.isEmpty()) {
+            return variantCode;
         }
         return result;
     }
@@ -1125,7 +1167,10 @@
      * @throws MissingResourceException if there's no 3-letter country code for this locale.
      */
     public String getISO3Country() {
-        String code = ICU.getISO3CountryNative(getIcuLocaleId());
+        // The results of getISO3Country do not depend on the languageCode,
+        // so we pass an arbitrarily selected language code here. This guards
+        // against errors caused by malformed or invalid language codes.
+        String code = ICU.getISO3Country("en-" + countryCode);
         if (!countryCode.isEmpty() && code.isEmpty()) {
             throw new MissingResourceException("No 3-letter country code for locale: " + this, "FormatData_" + this, "ShortCountry");
         }
@@ -1138,7 +1183,16 @@
      * @throws MissingResourceException if there's no 3-letter language code for this locale.
      */
     public String getISO3Language() {
-        String code = ICU.getISO3LanguageNative(getIcuLocaleId());
+        // For backward compatibility, we must return "" for an empty language
+        // code and not "und" which is the accurate ISO-639-3 code for an
+        // undetermined language.
+        if (languageCode.isEmpty()) {
+            return "";
+        }
+
+        // The results of getISO3Language do not depend on the country code
+        // or any of the other locale fields, so we pass just the language here.
+        String code = ICU.getISO3Language(languageCode);
         if (!languageCode.isEmpty() && code.isEmpty()) {
             throw new MissingResourceException("No 3-letter language code for locale: " + this, "FormatData_" + this, "ShortLanguage");
         }
@@ -1214,10 +1268,9 @@
             return "";
         }
 
-        String result = ICU.getDisplayScriptNative(getIcuLocaleId(), locale.getIcuLocaleId());
+        String result = ICU.getDisplayScript(this, locale);
         if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
-            result = ICU.getDisplayScriptNative(getIcuLocaleId(),
-                    Locale.getDefault().getIcuLocaleId());
+            result = ICU.getDisplayScript(this, Locale.getDefault());
         }
 
         return result;
@@ -1238,7 +1291,7 @@
      * where they will appear after a subtag whose value is {@code "lvariant"}.
      *
      * It's also important to note that the BCP-47 tag is well formed in the sense
-     * that it is unambiguously parsable into its specified components. We do not
+     * that it is unambiguously parseable into its specified components. We do not
      * require that any of the components are registered with the applicable registries.
      * For example, we do not require scripts to be a registered ISO 15924 scripts or
      * languages to appear in the ISO-639-2 code list.
@@ -1248,13 +1301,212 @@
      */
     public String toLanguageTag() {
         if (cachedLanguageTag == null) {
-            cachedLanguageTag = ICU.toLanguageTag(this);
+            cachedLanguageTag = makeLanguageTag();
         }
 
         return cachedLanguageTag;
     }
 
     /**
+     * Constructs a valid BCP-47 language tag from locale fields. Additional validation
+     * is required when this Locale was not constructed using a Builder and variants
+     * set this way are treated specially.
+     *
+     * In both cases, we convert empty language tags to "und", omit invalid country tags
+     * and perform a special case conversion of "no-NO-NY" to "nn-NO".
+     */
+    private String makeLanguageTag() {
+        // We only need to revalidate the language, country and variant because
+        // the rest of the fields can only be set via the builder which validates
+        // them anyway.
+        String language = "";
+        String region = "";
+        String variant = "";
+        String illFormedVariantSubtags = "";
+
+        if (hasValidatedFields) {
+            language = languageCode;
+            region = countryCode;
+            // Note that we are required to normalize hyphens to underscores
+            // in the builder, but we must use hyphens in the BCP-47 language tag.
+            variant = variantCode.replace('_', '-');
+        } else {
+            try {
+                language = Builder.normalizeAndValidateLanguage(languageCode);
+            } catch (IllformedLocaleException ilfe) {
+                // Ignored, continue processing with "".
+            }
+
+            try {
+                region = Builder.normalizeAndValidateRegion(countryCode);
+            } catch (IllformedLocaleException ilfe) {
+                // Ignored, continue processing with "".
+            }
+
+            try {
+                variant = Builder.normalizeAndValidateVariant(variantCode);
+            } catch (IllformedLocaleException ilfe) {
+                // If our variant is ill formed, we must attempt to split it into
+                // its constituent subtags and preserve the well formed bits and
+                // move the rest to the private use extension (if they're well
+                // formed extension subtags).
+                String split[] = splitIllformedVariant(variantCode);
+
+                variant = split[0];
+                illFormedVariantSubtags = split[1];
+            }
+        }
+
+        if (language.isEmpty()) {
+            language = "und";
+        }
+
+        if ("no".equals(language) && "NO".equals(region) && "NY".equals(variant)) {
+            language = "nn";
+            region = "NO";
+            variant = "";
+        }
+
+        final StringBuilder sb = new StringBuilder(16);
+        sb.append(language);
+
+        if (!scriptCode.isEmpty()) {
+            sb.append('-');
+            sb.append(scriptCode);
+        }
+
+        if (!region.isEmpty()) {
+            sb.append('-');
+            sb.append(region);
+        }
+
+        if (!variant.isEmpty()) {
+            sb.append('-');
+            sb.append(variant);
+        }
+
+        // Extensions (optional, omitted if empty). Note that we don't
+        // emit the private use extension here, but add it in the end.
+        for (Map.Entry<Character, String> extension : extensions.entrySet()) {
+            if (!extension.getKey().equals('x')) {
+                sb.append('-').append(extension.getKey());
+                sb.append('-').append(extension.getValue());
+            }
+        }
+
+        // The private use extension comes right at the very end.
+        final String privateUse = extensions.get('x');
+        if (privateUse != null) {
+            sb.append("-x-");
+            sb.append(privateUse);
+        }
+
+        // If we have any ill-formed variant subtags, we append them to the
+        // private use extension (or add a private use extension if one doesn't
+        // exist).
+        if (!illFormedVariantSubtags.isEmpty()) {
+            if (privateUse == null) {
+                sb.append("-x-lvariant-");
+            } else {
+                sb.append('-');
+            }
+            sb.append(illFormedVariantSubtags);
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Splits ill formed variants into a set of valid variant subtags (which
+     * can be used directly in language tag construction) and a set of invalid
+     * variant subtags (which can be appended to the private use extension),
+     * provided that each subtag is a valid private use extension subtag.
+     *
+     * This method returns a two element String array. The first element is a string
+     * containing the concatenation of valid variant subtags which can be appended
+     * to a BCP-47 tag directly and the second containing the concatenation of
+     * invalid variant subtags which can be appended to the private use extension
+     * directly.
+     *
+     * This method assumes that {@code variant} contains at least one ill formed
+     * variant subtag.
+     */
+    private static String[] splitIllformedVariant(String variant) {
+        final String normalizedVariant = variant.replace('_', '-');
+        final String[] subTags = normalizedVariant.split("-");
+
+        final String[] split = new String[] { "", "" };
+
+        // First go through the list of variant subtags and check if they're
+        // valid private use extension subtags. If they're not, we will omit
+        // the first such subtag and all subtags after.
+        //
+        // NOTE: |firstInvalidSubtag| is the index of the first variant
+        // subtag we decide to omit altogether, whereas |firstIllformedSubtag| is the
+        // index of the first subtag we decide to append to the private use extension.
+        //
+        // In other words:
+        // [0, firstIllformedSubtag) => expressed as variant subtags.
+        // [firstIllformedSubtag, firstInvalidSubtag) => expressed as private use
+        // extension subtags.
+        // [firstInvalidSubtag, subTags.length) => omitted.
+        int firstInvalidSubtag = subTags.length;
+        for (int i = 0; i < subTags.length; ++i) {
+            if (!isValidBcp47Alphanum(subTags[i], 1, 8)) {
+                firstInvalidSubtag = i;
+                break;
+            }
+        }
+
+        if (firstInvalidSubtag == 0) {
+            return split;
+        }
+
+        // We now consider each subtag that could potentially be appended to
+        // the private use extension and check if it's valid.
+        int firstIllformedSubtag = firstInvalidSubtag;
+        for (int i = 0; i < firstInvalidSubtag; ++i) {
+            final String subTag = subTags[i];
+            // The BCP-47 spec states that :
+            // - Subtags can be between [5, 8] alphanumeric chars in length.
+            // - Subtags that start with a number are allowed to be 4 chars in length.
+            if (subTag.length() >= 5 && subTag.length() <= 8) {
+                if (!isAsciiAlphaNum(subTag)) {
+                    firstIllformedSubtag = i;
+                }
+            } else if (subTag.length() == 4) {
+                final char firstChar = subTag.charAt(0);
+                if (!(firstChar >= '0' && firstChar <= '9') || !isAsciiAlphaNum(subTag)) {
+                    firstIllformedSubtag = i;
+                }
+            } else {
+                firstIllformedSubtag = i;
+            }
+        }
+
+        split[0] = concatenateRange(subTags, 0, firstIllformedSubtag);
+        split[1] = concatenateRange(subTags, firstIllformedSubtag, firstInvalidSubtag);
+
+        return split;
+    }
+
+    /**
+     * Builds a string by concatenating array elements within the range [start, end).
+     * The supplied range is assumed to be valid and no checks are performed.
+     */
+    private static String concatenateRange(String[] array, int start, int end) {
+        StringBuilder builder = new StringBuilder(32);
+        for (int i = start; i < end; ++i) {
+            if (i != 0) {
+                builder.append('-');
+            }
+            builder.append(array[i]);
+        }
+
+        return builder.toString();
+    }
+
+    /**
      * Returns the set of BCP-47 extensions this locale contains.
      *
      * See <a href="https://tools.ietf.org/html/bcp47#section-2.1">
@@ -1340,8 +1592,9 @@
         if (locale == null) {
             throw new NullPointerException("locale == null");
         }
+        String languageTag = locale.toLanguageTag();
         defaultLocale = locale;
-        ICU.setDefaultLocale(ICU.localeIdFromLocale(locale));
+        ICU.setDefaultLocale(languageTag);
     }
 
     /**
@@ -1359,20 +1612,12 @@
     public final String toString() {
         String result = cachedToStringResult;
         if (result == null) {
-            result = cachedToStringResult = toNewString(languageCode, countryCode,
-                    variantCode, scriptCode, extensions);
+            result = cachedToStringResult = toNewString(languageCode, countryCode, variantCode,
+                                                        scriptCode, extensions);
         }
         return result;
     }
 
-    private String getIcuLocaleId() {
-        if (cachedIcuLocaleId == null) {
-            cachedIcuLocaleId = ICU.localeIdFromLocale(this);
-        }
-
-        return cachedIcuLocaleId;
-    }
-
     private static String toNewString(String languageCode, String countryCode,
             String variantCode, String scriptCode, Map<Character, String> extensions) {
         // The string form of a locale that only has a variant is the empty string.
@@ -1387,8 +1632,7 @@
         StringBuilder result = new StringBuilder(11);
         result.append(languageCode);
 
-        final boolean hasScriptOrExtensions = !scriptCode.isEmpty() ||
-                !extensions.isEmpty();
+        final boolean hasScriptOrExtensions = !scriptCode.isEmpty() || !extensions.isEmpty();
 
         if (!countryCode.isEmpty() || !variantCode.isEmpty() || hasScriptOrExtensions) {
             result.append('_');
@@ -1594,8 +1838,7 @@
         return true;
     }
 
-    private static boolean isValidBcp47Alpha(String string,
-            int lowerBound, int upperBound) {
+    private static boolean isValidBcp47Alpha(String string, int lowerBound, int upperBound) {
         final int length = string.length();
         if (length < lowerBound || length > upperBound) {
             return false;
diff --git a/luni/src/main/java/libcore/icu/ICU.java b/luni/src/main/java/libcore/icu/ICU.java
index f60f427..33c899e 100644
--- a/luni/src/main/java/libcore/icu/ICU.java
+++ b/luni/src/main/java/libcore/icu/ICU.java
@@ -70,10 +70,6 @@
     return localeFromIcuLocaleId(icuLocaleId);
   }
 
-  public static String toLanguageTag(Locale locale) {
-    return languageTagForLocale(localeIdFromLocale(locale));
-  }
-
   private static final int IDX_LANGUAGE = 0;
   private static final int IDX_SCRIPT = 1;
   private static final int IDX_REGION = 2;
@@ -239,71 +235,8 @@
 
     return new Locale(outputArray[IDX_LANGUAGE], outputArray[IDX_REGION],
         outputArray[IDX_VARIANT], outputArray[IDX_SCRIPT],
-        unicodeAttributeSet, unicodeKeywordsMap, extensionsMap, false);
-  }
-
-  /**
-   * Builds an ICU locale ID from the given locale. The format is very
-   * straightforward. It is a series of subtags in BCP 47 order
-   * {@code lang[_script][_country][_variant]} followed by the keyword
-   * separator {@code @} followed by a list of keywords. Each keyword is
-   * a key value pair, and appear in the form {@code k1=v1;k2=v2;...}.
-   *
-   * In this use case, each key is an extension identifier, and each value
-   * is the value of the extension.
-   */
-  public static String localeIdFromLocale(Locale l) {
-      StringBuilder b = new StringBuilder(16);
-      b.append(l.getLanguage());
-
-      final boolean hasScript = !l.getScript().isEmpty();
-      final boolean hasCountry = !l.getCountry().isEmpty();
-      final boolean hasVariant = !l.getVariant().isEmpty();
-
-      if (hasScript || hasCountry || hasVariant) {
-          b.append('_');
-          if (hasScript) {
-              b.append(l.getScript());
-              if (hasCountry || hasVariant) {
-                  b.append('_');
-              }
-          }
-
-          if (hasCountry) {
-              b.append(l.getCountry());
-              if (hasVariant) {
-                  b.append('_');
-              }
-          }
-
-          b.append(l.getVariant());
-      }
-
-      if (!l.getExtensionKeys().isEmpty()) {
-        b.append('@');
-        // The private use extension ('x') must show up last in the list
-        // so we cache its value here and append it right at the end.
-        String privateUseExtensionValue = null;
-        for (char c : l.getExtensionKeys()) {
-          if (c == Locale.PRIVATE_USE_EXTENSION) {
-            privateUseExtensionValue = l.getExtension(Locale.PRIVATE_USE_EXTENSION);
-          } else {
-            b.append(c);
-            b.append('=');
-            b.append(l.getExtension(c));
-            b.append(';');
-          }
-        }
-
-        if (privateUseExtensionValue != null) {
-          b.append(Locale.PRIVATE_USE_EXTENSION);
-          b.append('=');
-          b.append(privateUseExtensionValue);
-          b.append(';');
-        }
-      }
-
-      return b.toString();
+        unicodeAttributeSet, unicodeKeywordsMap, extensionsMap,
+        true /* has validated fields */);
   }
 
   public static Locale[] localesFromStrings(String[] localeNames) {
@@ -352,19 +285,20 @@
     return localesFromStrings(getAvailableNumberFormatLocalesNative());
   }
 
-  public static String getBestDateTimePattern(String skeleton, String localeName) {
-    String key = skeleton + "\t" + localeName;
+  public static String getBestDateTimePattern(String skeleton, Locale locale) {
+    String languageTag = locale.toLanguageTag();
+    String key = skeleton + "\t" + languageTag;
     synchronized (CACHED_PATTERNS) {
       String pattern = CACHED_PATTERNS.get(key);
       if (pattern == null) {
-        pattern = getBestDateTimePatternNative(skeleton, localeName);
+        pattern = getBestDateTimePatternNative(skeleton, languageTag);
         CACHED_PATTERNS.put(key, pattern);
       }
       return pattern;
     }
   }
 
-  private static native String getBestDateTimePatternNative(String skeleton, String localeName);
+  private static native String getBestDateTimePatternNative(String skeleton, String languageTag);
 
   public static char[] getDateFormatOrder(String pattern) {
     char[] result = new char[3];
@@ -424,8 +358,17 @@
 
   // --- Case mapping.
 
-  public static native String toLowerCase(String s, String localeName);
-  public static native String toUpperCase(String s, String localeName);
+  public static String toLowerCase(String s, Locale locale) {
+    return toLowerCase(s, locale.toLanguageTag());
+  }
+
+  private static native String toLowerCase(String s, String languageTag);
+
+  public static String toUpperCase(String s, Locale locale) {
+    return toUpperCase(s, locale.toLanguageTag());
+  }
+
+  private static native String toUpperCase(String s, String languageTag);
 
   // --- Errors.
 
@@ -451,18 +394,49 @@
 
   public static native String[] getAvailableCurrencyCodes();
   public static native String getCurrencyCode(String countryCode);
-  public static native String getCurrencyDisplayName(String locale, String currencyCode);
+
+  public static String getCurrencyDisplayName(Locale locale, String currencyCode) {
+    return getCurrencyDisplayName(locale.toLanguageTag(), currencyCode);
+  }
+
+  private static native String getCurrencyDisplayName(String languageTag, String currencyCode);
+
   public static native int getCurrencyFractionDigits(String currencyCode);
   public static native int getCurrencyNumericCode(String currencyCode);
-  public static native String getCurrencySymbol(String locale, String currencyCode);
 
-  public static native String getDisplayCountryNative(String countryCode, String locale);
-  public static native String getDisplayLanguageNative(String languageCode, String locale);
-  public static native String getDisplayVariantNative(String variantCode, String locale);
-  public static native String getDisplayScriptNative(String variantCode, String locale);
+  public static String getCurrencySymbol(Locale locale, String currencyCode) {
+    return getCurrencySymbol(locale.toLanguageTag(), currencyCode);
+  }
 
-  public static native String getISO3CountryNative(String locale);
-  public static native String getISO3LanguageNative(String locale);
+  private static native String getCurrencySymbol(String languageTag, String currencyCode);
+
+  public static String getDisplayCountry(Locale targetLocale, Locale locale) {
+    return getDisplayCountryNative(targetLocale.toLanguageTag(), locale.toLanguageTag());
+  }
+
+  private static native String getDisplayCountryNative(String targetLanguageTag, String languageTag);
+
+  public static String getDisplayLanguage(Locale targetLocale, Locale locale) {
+    return getDisplayLanguageNative(targetLocale.toLanguageTag(), locale.toLanguageTag());
+  }
+
+  private static native String getDisplayLanguageNative(String targetLanguageTag, String languageTag);
+
+  public static String getDisplayVariant(Locale targetLocale, Locale locale) {
+    return getDisplayVariantNative(targetLocale.toLanguageTag(), locale.toLanguageTag());
+  }
+
+  private static native String getDisplayVariantNative(String targetLanguageTag, String languageTag);
+
+  public static String getDisplayScript(Locale targetLocale, Locale locale) {
+    return getDisplayScriptNative(targetLocale.toLanguageTag(), locale.toLanguageTag());
+  }
+
+  private static native String getDisplayScriptNative(String targetLanguageTag, String languageTag);
+
+  public static native String getISO3Country(String languageTag);
+
+  public static native String getISO3Language(String languageTag);
 
   public static native String addLikelySubtags(String locale);
   public static native String getScript(String locale);
@@ -471,10 +445,16 @@
   private static native String[] getISOCountriesNative();
 
   private static native String localeForLanguageTag(String languageTag, boolean strict);
-  public static native String languageTagForLocale(String locale);
 
   static native boolean initLocaleDataNative(String locale, LocaleData result);
 
-  public static native void setDefaultLocale(String locale);
+  /**
+   * Takes a BCP-47 language tag (Locale.toLanguageTag()). e.g. en-US, not en_US
+   */
+  public static native void setDefaultLocale(String languageTag);
+
+  /**
+   * Returns a locale name, not a BCP-47 language tag. e.g. en_US not en-US.
+   */
   public static native String getDefaultLocale();
 }
diff --git a/luni/src/main/java/libcore/icu/LocaleData.java b/luni/src/main/java/libcore/icu/LocaleData.java
index 49228b3..845ba32 100644
--- a/luni/src/main/java/libcore/icu/LocaleData.java
+++ b/luni/src/main/java/libcore/icu/LocaleData.java
@@ -176,8 +176,8 @@
         }
 
         // Get the "h:mm a" and "HH:mm" 12- and 24-hour time format strings.
-        localeData.timeFormat12 = ICU.getBestDateTimePattern("hm", locale.toString());
-        localeData.timeFormat24 = ICU.getBestDateTimePattern("Hm", locale.toString());
+        localeData.timeFormat12 = ICU.getBestDateTimePattern("hm", locale);
+        localeData.timeFormat24 = ICU.getBestDateTimePattern("Hm", locale);
 
         // Fix up a couple of patterns.
         if (localeData.fullTimeFormat != null) {
diff --git a/luni/src/main/java/libcore/icu/NativeBreakIterator.java b/luni/src/main/java/libcore/icu/NativeBreakIterator.java
index 7168d96..992aac2 100644
--- a/luni/src/main/java/libcore/icu/NativeBreakIterator.java
+++ b/luni/src/main/java/libcore/icu/NativeBreakIterator.java
@@ -138,23 +138,23 @@
     }
 
     public int preceding(int offset) {
-      return precedingImpl(this.address, this.string, offset);
+        return precedingImpl(this.address, this.string, offset);
     }
 
-    public static NativeBreakIterator getCharacterInstance(Locale where) {
-        return new NativeBreakIterator(getCharacterInstanceImpl(where.toString()), BI_CHAR_INSTANCE);
+    public static NativeBreakIterator getCharacterInstance(Locale locale) {
+        return new NativeBreakIterator(getCharacterInstanceImpl(locale.toLanguageTag()), BI_CHAR_INSTANCE);
     }
 
-    public static NativeBreakIterator getLineInstance(Locale where) {
-        return new NativeBreakIterator(getLineInstanceImpl(where.toString()), BI_LINE_INSTANCE);
+    public static NativeBreakIterator getLineInstance(Locale locale) {
+        return new NativeBreakIterator(getLineInstanceImpl(locale.toLanguageTag()), BI_LINE_INSTANCE);
     }
 
-    public static NativeBreakIterator getSentenceInstance(Locale where) {
-        return new NativeBreakIterator(getSentenceInstanceImpl(where.toString()), BI_SENT_INSTANCE);
+    public static NativeBreakIterator getSentenceInstance(Locale locale) {
+        return new NativeBreakIterator(getSentenceInstanceImpl(locale.toLanguageTag()), BI_SENT_INSTANCE);
     }
 
-    public static NativeBreakIterator getWordInstance(Locale where) {
-        return new NativeBreakIterator(getWordInstanceImpl(where.toString()), BI_WORD_INSTANCE);
+    public static NativeBreakIterator getWordInstance(Locale locale) {
+        return new NativeBreakIterator(getWordInstanceImpl(locale.toLanguageTag()), BI_WORD_INSTANCE);
     }
 
     private static native long getCharacterInstanceImpl(String locale);
diff --git a/luni/src/main/java/libcore/icu/NativeCollation.java b/luni/src/main/java/libcore/icu/NativeCollation.java
index 64e0278..b4b4f46 100644
--- a/luni/src/main/java/libcore/icu/NativeCollation.java
+++ b/luni/src/main/java/libcore/icu/NativeCollation.java
@@ -10,6 +10,8 @@
 
 package libcore.icu;
 
+import java.util.Locale;
+
 /**
 * Package static class for declaring all native methods for collation use.
 * @author syn wee quek
@@ -26,7 +28,10 @@
     public static native long getCollationElementIterator(long address, String source);
     public static native String getRules(long address);
     public static native byte[] getSortKey(long address, String source);
-    public static native long openCollator(String locale);
+    public static long openCollator(Locale locale) {
+      return openCollator(locale.toLanguageTag());
+    }
+    private static native long openCollator(String languageTag);
     public static native long openCollatorFromRules(String rules, int normalizationMode, int collationStrength);
     public static native long safeClone(long address);
     public static native void setAttribute(long address, int type, int value);
diff --git a/luni/src/main/java/libcore/icu/NativeDecimalFormat.java b/luni/src/main/java/libcore/icu/NativeDecimalFormat.java
index f512002..fd179c1 100644
--- a/luni/src/main/java/libcore/icu/NativeDecimalFormat.java
+++ b/luni/src/main/java/libcore/icu/NativeDecimalFormat.java
@@ -475,9 +475,9 @@
         setAttribute(this.address, UNUM_DECIMAL_ALWAYS_SHOWN, i);
     }
 
-    public void setCurrency(Currency currency) {
-        setSymbol(this.address, UNUM_CURRENCY_SYMBOL, currency.getSymbol());
-        setSymbol(this.address, UNUM_INTL_CURRENCY_SYMBOL, currency.getCurrencyCode());
+    public void setCurrency(String currencySymbol, String currencyCode) {
+        setSymbol(this.address, UNUM_CURRENCY_SYMBOL, currencySymbol);
+        setSymbol(this.address, UNUM_INTL_CURRENCY_SYMBOL, currencyCode);
     }
 
     public void setGroupingSize(int value) {
diff --git a/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java b/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
index 3ea942d..b23013b 100644
--- a/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
+++ b/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
@@ -52,7 +52,7 @@
     }
 
     public RuleBasedCollatorICU(Locale locale) {
-        address = NativeCollation.openCollator(locale.toString());
+        address = NativeCollation.openCollator(locale);
     }
 
     private RuleBasedCollatorICU(long address) {
diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp
index c6f3950..7ce2168 100644
--- a/luni/src/main/native/IcuUtilities.cpp
+++ b/luni/src/main/native/IcuUtilities.cpp
@@ -28,10 +28,6 @@
 #include "unicode/uloc.h"
 #include "unicode/ustring.h"
 
-Locale getLocale(JNIEnv* env, jstring localeName) {
-  return Locale::createFromName(ScopedUtfChars(env, localeName).c_str());
-}
-
 jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, StringEnumeration* se) {
   if (maybeThrowIcuException(env, provider, status)) {
     return NULL;
diff --git a/luni/src/main/native/IcuUtilities.h b/luni/src/main/native/IcuUtilities.h
index ffcfcda..737379e 100644
--- a/luni/src/main/native/IcuUtilities.h
+++ b/luni/src/main/native/IcuUtilities.h
@@ -23,9 +23,7 @@
 #include "jni.h"
 #include "ustrenum.h" // For UStringEnumeration.
 #include "unicode/utypes.h" // For UErrorCode.
-#include "unicode/locid.h" // For Locale.
 
-extern Locale getLocale(JNIEnv* env, jstring localeName);
 extern jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, StringEnumeration*);
 bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error);
 
diff --git a/luni/src/main/native/Portability.h b/luni/src/main/native/Portability.h
index 60b7062..fb60ed4 100644
--- a/luni/src/main/native/Portability.h
+++ b/luni/src/main/native/Portability.h
@@ -64,7 +64,6 @@
 // For statfs(3).
 #include <sys/param.h>
 #include <sys/mount.h>
-#define f_frsize f_bsize // TODO: close enough?
 
 #else
 
diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp
index cc3054a..87ebc21 100644
--- a/luni/src/main/native/android_system_OsConstants.cpp
+++ b/luni/src/main/native/android_system_OsConstants.cpp
@@ -30,15 +30,19 @@
 #include <stdlib.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
+#ifndef __APPLE__
 #include <sys/prctl.h>
+#endif
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
 // After the others because these are not necessarily self-contained in glibc.
+#ifndef __APPLE__
 #include <linux/if_addr.h>
 #include <linux/rtnetlink.h>
+#endif
 
 #include <net/if.h> // After <sys/socket.h> to work around a Mac header file bug.
 
@@ -229,14 +233,30 @@
 #if defined(IFA_F_DADFAILED)
     initConstant(env, c, "IFA_F_DADFAILED", IFA_F_DADFAILED);
 #endif
+#if defined(IFA_F_DEPRECATED)
     initConstant(env, c, "IFA_F_DEPRECATED", IFA_F_DEPRECATED);
+#endif
+#if defined(IFA_F_HOMEADDRESS)
     initConstant(env, c, "IFA_F_HOMEADDRESS", IFA_F_HOMEADDRESS);
+#endif
+#if defined(IFA_F_NODAD)
     initConstant(env, c, "IFA_F_NODAD", IFA_F_NODAD);
+#endif
+#if defined(IFA_F_OPTIMISTIC)
     initConstant(env, c, "IFA_F_OPTIMISTIC", IFA_F_OPTIMISTIC);
+#endif
+#if defined(IFA_F_PERMANENT)
     initConstant(env, c, "IFA_F_PERMANENT", IFA_F_PERMANENT);
+#endif
+#if defined(IFA_F_SECONDARY)
     initConstant(env, c, "IFA_F_SECONDARY", IFA_F_SECONDARY);
+#endif
+#if defined(IFA_F_TEMPORARY)
     initConstant(env, c, "IFA_F_TEMPORARY", IFA_F_TEMPORARY);
+#endif
+#if defined(IFA_F_TENTATIVE)
     initConstant(env, c, "IFA_F_TENTATIVE", IFA_F_TENTATIVE);
+#endif
     initConstant(env, c, "IFF_ALLMULTI", IFF_ALLMULTI);
 #if defined(IFF_AUTOMEDIA)
     initConstant(env, c, "IFF_AUTOMEDIA", IFF_AUTOMEDIA);
@@ -370,11 +390,17 @@
     initConstant(env, c, "PROT_READ", PROT_READ);
     initConstant(env, c, "PROT_WRITE", PROT_WRITE);
     initConstant(env, c, "R_OK", R_OK);
+// NOTE: The RT_* constants are not preprocessor defines, they're enum
+// members. The best we can do (barring UAPI / kernel version checks) is
+// to hope they exist on all host linuxes we're building on. These
+// constants have been around since 2.6.35 at least, so we should be ok.
+#if !defined(__APPLE__)
     initConstant(env, c, "RT_SCOPE_HOST", RT_SCOPE_HOST);
     initConstant(env, c, "RT_SCOPE_LINK", RT_SCOPE_LINK);
     initConstant(env, c, "RT_SCOPE_NOWHERE", RT_SCOPE_NOWHERE);
     initConstant(env, c, "RT_SCOPE_SITE", RT_SCOPE_SITE);
     initConstant(env, c, "RT_SCOPE_UNIVERSE", RT_SCOPE_UNIVERSE);
+#endif
     initConstant(env, c, "SEEK_CUR", SEEK_CUR);
     initConstant(env, c, "SEEK_END", SEEK_END);
     initConstant(env, c, "SEEK_SET", SEEK_SET);
@@ -441,8 +467,12 @@
     initConstant(env, c, "SO_KEEPALIVE", SO_KEEPALIVE);
     initConstant(env, c, "SO_LINGER", SO_LINGER);
     initConstant(env, c, "SO_OOBINLINE", SO_OOBINLINE);
+#if defined(SO_PASSCRED)
     initConstant(env, c, "SO_PASSCRED", SO_PASSCRED);
+#endif
+#if defined(SO_PEERCRED)
     initConstant(env, c, "SO_PEERCRED", SO_PEERCRED);
+#endif
     initConstant(env, c, "SO_RCVBUF", SO_RCVBUF);
     initConstant(env, c, "SO_RCVLOWAT", SO_RCVLOWAT);
     initConstant(env, c, "SO_RCVTIMEO", SO_RCVTIMEO);
diff --git a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
index bb05193..e0638bd 100644
--- a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
+++ b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
@@ -20,6 +20,7 @@
 #include "JNIHelp.h"
 #include "JniConstants.h"
 #include "JniException.h"
+#include "ScopedIcuLocale.h"
 #include "ScopedJavaUnicodeString.h"
 #include "unicode/alphaindex.h"
 #include "unicode/uniset.h"
@@ -28,9 +29,13 @@
   return reinterpret_cast<AlphabeticIndex*>(static_cast<uintptr_t>(peer));
 }
 
-static jlong AlphabeticIndex_create(JNIEnv* env, jclass, jstring javaLocale) {
+static jlong AlphabeticIndex_create(JNIEnv* env, jclass, jstring javaLocaleName) {
   UErrorCode status = U_ZERO_ERROR;
-  AlphabeticIndex* ai = new AlphabeticIndex(getLocale(env, javaLocale), status);
+  ScopedIcuLocale icuLocale(env, javaLocaleName);
+  if (!icuLocale.valid()) {
+    return 0;
+  }
+  AlphabeticIndex* ai = new AlphabeticIndex(icuLocale.locale(), status);
   if (maybeThrowIcuException(env, "AlphabeticIndex", status)) {
     return 0;
   }
@@ -53,10 +58,14 @@
   maybeThrowIcuException(env, "AlphabeticIndex::setMaxLabelCount", status);
 }
 
-static void AlphabeticIndex_addLabels(JNIEnv* env, jclass, jlong peer, jstring javaLocale) {
+static void AlphabeticIndex_addLabels(JNIEnv* env, jclass, jlong peer, jstring javaLocaleName) {
   AlphabeticIndex* ai = fromPeer(peer);
+  ScopedIcuLocale icuLocale(env, javaLocaleName);
+  if (!icuLocale.valid()) {
+    return;
+  }
   UErrorCode status = U_ZERO_ERROR;
-  ai->addLabels(getLocale(env, javaLocale), status);
+  ai->addLabels(icuLocale.locale(), status);
   maybeThrowIcuException(env, "AlphabeticIndex::addLabels", status);
 }
 
diff --git a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
index 72bc631..a3258c1 100644
--- a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
+++ b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
@@ -18,13 +18,17 @@
 
 #include "IcuUtilities.h"
 #include "JniConstants.h"
+#include "ScopedIcuLocale.h"
 #include "ScopedJavaUnicodeString.h"
 #include "UniquePtr.h"
 #include "cutils/log.h"
 #include "unicode/dtitvfmt.h"
 
 static jlong DateIntervalFormat_createDateIntervalFormat(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName, jstring javaTzName) {
-  Locale locale = getLocale(env, javaLocaleName);
+  ScopedIcuLocale icuLocale(env, javaLocaleName);
+  if (!icuLocale.valid()) {
+    return 0;
+  }
 
   ScopedJavaUnicodeString skeletonHolder(env, javaSkeleton);
   if (!skeletonHolder.valid()) {
@@ -32,7 +36,7 @@
   }
 
   UErrorCode status = U_ZERO_ERROR;
-  DateIntervalFormat* formatter(DateIntervalFormat::createInstance(skeletonHolder.unicodeString(), locale, status));
+  DateIntervalFormat* formatter(DateIntervalFormat::createInstance(skeletonHolder.unicodeString(), icuLocale.locale(), status));
   if (maybeThrowIcuException(env, "DateIntervalFormat::createInstance", status)) {
     return 0;
   }
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index cc51722..163d19c 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -21,6 +21,7 @@
 #include "JniConstants.h"
 #include "JniException.h"
 #include "ScopedFd.h"
+#include "ScopedIcuLocale.h"
 #include "ScopedJavaUnicodeString.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
@@ -96,30 +97,30 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedResourceBundle);
 };
 
-static jstring ICU_addLikelySubtags(JNIEnv* env, jclass, jstring javaLocale) {
+static jstring ICU_addLikelySubtags(JNIEnv* env, jclass, jstring javaLocaleName) {
     UErrorCode status = U_ZERO_ERROR;
-    ScopedUtfChars localeID(env, javaLocale);
+    ScopedUtfChars localeID(env, javaLocaleName);
     char maximizedLocaleID[ULOC_FULLNAME_CAPACITY];
     uloc_addLikelySubtags(localeID.c_str(), maximizedLocaleID, sizeof(maximizedLocaleID), &status);
     if (U_FAILURE(status)) {
-        return javaLocale;
+        return javaLocaleName;
     }
     return env->NewStringUTF(maximizedLocaleID);
 }
 
-static jstring ICU_getScript(JNIEnv* env, jclass, jstring javaLocale) {
-    UErrorCode status = U_ZERO_ERROR;
-    ScopedUtfChars localeID(env, javaLocale);
-    char script[ULOC_SCRIPT_CAPACITY];
-    uloc_getScript(localeID.c_str(), script, sizeof(script), &status);
-    if (U_FAILURE(status)) {
-        return NULL;
-    }
-    return env->NewStringUTF(script);
+static jstring ICU_getScript(JNIEnv* env, jclass, jstring javaLocaleName) {
+  ScopedIcuLocale icuLocale(env, javaLocaleName);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
+  return env->NewStringUTF(icuLocale.locale().getScript());
 }
 
 static jstring ICU_localeForLanguageTag(JNIEnv* env, jclass, jstring languageTag, jboolean strict) {
     ScopedUtfChars languageTagChars(env, languageTag);
+    if (languageTagChars.c_str() == NULL) {
+      return NULL;
+    }
 
     // Naively assume that in the average case, the size of
     // the normalized language tag will be very nearly the same as the
@@ -131,23 +132,23 @@
     int32_t parsedLength = 0;
 
     UErrorCode status = U_ZERO_ERROR;
-    while (true) {
-        const size_t outputLength = uloc_forLanguageTag(languageTagChars.c_str(),
-               &buffer[0], buffer.size(), &parsedLength, &status);
-        if (U_FAILURE(status)) {
-            return NULL;
-        }
-
-        // Assume that we've run out of buffer space when this happens. Double
-        // the buffer size and try again. This should happen very infrequently.
-        if (outputLength == buffer.size()) {
-            buffer.resize(buffer.size() << 1);
-        } else {
-            break;
-        }
+    size_t outputLength = uloc_forLanguageTag(languageTagChars.c_str(), &buffer[0],
+                                              buffer.size(), &parsedLength, &status);
+    // Note that we always allocate 1 char more than ICU asks us for,
+    // so that we can cleanly assert that it didn't overflow after the
+    // second call to uloc_forLanguageTag.
+    if (status == U_STRING_NOT_TERMINATED_WARNING) {
+        const size_t unterminated_size = buffer.size();
+        buffer.resize(unterminated_size + 1);
+        buffer[unterminated_size] = '\0';
+    } else if (status == U_BUFFER_OVERFLOW_ERROR) {
+        buffer.resize(outputLength + 1);
+        status = U_ZERO_ERROR;
+        outputLength = uloc_forLanguageTag(languageTagChars.c_str(), &buffer[0], buffer.size(),
+                                           &parsedLength, &status);
     }
 
-    if (parsedLength < 0) {
+    if (U_FAILURE(status) || outputLength >= buffer.size()) {
         return NULL;
     }
 
@@ -158,38 +159,7 @@
     // NOTE: The cast is safe because parsedLength can never be negative thanks
     // to the check above. ICU does not document any negative return values for
     // that field, but check for it anyway.
-    if ((strict == JNI_TRUE) &&
-        (static_cast<uint32_t>(parsedLength) != languageTagChars.size())) {
-        return NULL;
-    }
-
-    return env->NewStringUTF(&buffer[0]);
-}
-
-static jstring ICU_languageTagForLocale(JNIEnv* env, jclass, jstring javaLocaleId) {
-    ScopedUtfChars localeID(env, javaLocaleId);
-
-    // In most common cases, the BCP 47 tag will be the same size as the ICU
-    // locale ID
-    const size_t initialBufferSize = localeID.size() + 1;
-    std::vector<char> buffer(initialBufferSize);
-
-    UErrorCode status = U_ZERO_ERROR;
-    const size_t outputLength = uloc_toLanguageTag(localeID.c_str(),
-            &buffer[0], buffer.size(), false /* strict */, &status);
-    if (status == U_BUFFER_OVERFLOW_ERROR) {
-        buffer.resize(outputLength + 1);
-        status = U_ZERO_ERROR;
-        uloc_toLanguageTag(localeID.c_str(), &buffer[0], buffer.size(),
-                false /* strict */, &status);
-    }
-
-    if (status == U_STRING_NOT_TERMINATED_WARNING) {
-        buffer.resize(buffer.size() + 1);
-        buffer[buffer.size() -1] = '\0';
-    }
-
-    if (maybeThrowIcuException(env, "ICU::languageTagForLocale", status)) {
+    if ((strict == JNI_TRUE) && (static_cast<uint32_t>(parsedLength) != languageTagChars.size())) {
         return NULL;
     }
 
@@ -258,9 +228,9 @@
     return (charCount == 0) ? env->NewStringUTF("XXX") : env->NewString(chars, charCount);
 }
 
-static jstring getCurrencyName(JNIEnv* env, jstring javaLocaleName, jstring javaCurrencyCode, UCurrNameStyle nameStyle) {
-  ScopedUtfChars localeName(env, javaLocaleName);
-  if (localeName.c_str() == NULL) {
+static jstring getCurrencyName(JNIEnv* env, jstring javaLanguageTag, jstring javaCurrencyCode, UCurrNameStyle nameStyle) {
+  ScopedUtfChars languageTag(env, javaLanguageTag);
+  if (languageTag.c_str() == NULL) {
     return NULL;
   }
   ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode);
@@ -271,7 +241,7 @@
   UErrorCode status = U_ZERO_ERROR;
   UBool isChoiceFormat = false;
   int32_t charCount;
-  const UChar* chars = ucurr_getName(icuCurrencyCode.getTerminatedBuffer(), localeName.c_str(),
+  const UChar* chars = ucurr_getName(icuCurrencyCode.getTerminatedBuffer(), languageTag.c_str(),
                                      nameStyle, &isChoiceFormat, &charCount, &status);
   if (status == U_USING_DEFAULT_WARNING) {
     if (nameStyle == UCURR_SYMBOL_NAME) {
@@ -290,54 +260,88 @@
   return (charCount == 0) ? NULL : env->NewString(chars, charCount);
 }
 
-static jstring ICU_getCurrencyDisplayName(JNIEnv* env, jclass, jstring javaLocaleName, jstring javaCurrencyCode) {
-  return getCurrencyName(env, javaLocaleName, javaCurrencyCode, UCURR_LONG_NAME);
+static jstring ICU_getCurrencyDisplayName(JNIEnv* env, jclass, jstring javaLanguageTag, jstring javaCurrencyCode) {
+  return getCurrencyName(env, javaLanguageTag, javaCurrencyCode, UCURR_LONG_NAME);
 }
 
-static jstring ICU_getCurrencySymbol(JNIEnv* env, jclass, jstring javaLocaleName, jstring javaCurrencyCode) {
-  return getCurrencyName(env, javaLocaleName, javaCurrencyCode, UCURR_SYMBOL_NAME);
+static jstring ICU_getCurrencySymbol(JNIEnv* env, jclass, jstring javaLanguageTag, jstring javaCurrencyCode) {
+  return getCurrencyName(env, javaLanguageTag, javaCurrencyCode, UCURR_SYMBOL_NAME);
 }
 
-static jstring ICU_getDisplayCountryNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) {
-    Locale loc = getLocale(env, locale);
-    Locale targetLoc = getLocale(env, targetLocale);
-    UnicodeString str;
-    targetLoc.getDisplayCountry(loc, str);
-    return env->NewString(str.getBuffer(), str.length());
+static jstring ICU_getDisplayCountryNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) {
+  ScopedIcuLocale icuLocale(env, javaLanguageTag);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
+  ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag);
+  if (!icuTargetLocale.valid()) {
+    return NULL;
+  }
+
+  UnicodeString str;
+  icuTargetLocale.locale().getDisplayCountry(icuLocale.locale(), str);
+  return env->NewString(str.getBuffer(), str.length());
 }
 
-static jstring ICU_getDisplayLanguageNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) {
-    Locale loc = getLocale(env, locale);
-    Locale targetLoc = getLocale(env, targetLocale);
-    UnicodeString str;
-    targetLoc.getDisplayLanguage(loc, str);
-    return env->NewString(str.getBuffer(), str.length());
+static jstring ICU_getDisplayLanguageNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) {
+  ScopedIcuLocale icuLocale(env, javaLanguageTag);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
+  ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag);
+  if (!icuTargetLocale.valid()) {
+    return NULL;
+  }
+
+  UnicodeString str;
+  icuTargetLocale.locale().getDisplayLanguage(icuLocale.locale(), str);
+  return env->NewString(str.getBuffer(), str.length());
 }
 
-static jstring ICU_getDisplayScriptNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) {
-    Locale loc = getLocale(env, locale);
-    Locale targetLoc = getLocale(env, targetLocale);
-    UnicodeString str;
-    targetLoc.getDisplayScript(loc, str);
-    return env->NewString(str.getBuffer(), str.length());
+static jstring ICU_getDisplayScriptNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) {
+  ScopedIcuLocale icuLocale(env, javaLanguageTag);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
+  ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag);
+  if (!icuTargetLocale.valid()) {
+    return NULL;
+  }
+
+  UnicodeString str;
+  icuTargetLocale.locale().getDisplayScript(icuLocale.locale(), str);
+  return env->NewString(str.getBuffer(), str.length());
 }
 
-static jstring ICU_getDisplayVariantNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) {
-    Locale loc = getLocale(env, locale);
-    Locale targetLoc = getLocale(env, targetLocale);
-    UnicodeString str;
-    targetLoc.getDisplayVariant(loc, str);
-    return env->NewString(str.getBuffer(), str.length());
+static jstring ICU_getDisplayVariantNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) {
+  ScopedIcuLocale icuLocale(env, javaLanguageTag);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
+  ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag);
+  if (!icuTargetLocale.valid()) {
+    return NULL;
+  }
+
+  UnicodeString str;
+  icuTargetLocale.locale().getDisplayVariant(icuLocale.locale(), str);
+  return env->NewString(str.getBuffer(), str.length());
 }
 
-static jstring ICU_getISO3CountryNative(JNIEnv* env, jclass, jstring locale) {
-    Locale loc = getLocale(env, locale);
-    return env->NewStringUTF(loc.getISO3Country());
+static jstring ICU_getISO3Country(JNIEnv* env, jclass, jstring javaLanguageTag) {
+  ScopedIcuLocale icuLocale(env, javaLanguageTag);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
+  return env->NewStringUTF(icuLocale.locale().getISO3Country());
 }
 
-static jstring ICU_getISO3LanguageNative(JNIEnv* env, jclass, jstring locale) {
-    Locale loc = getLocale(env, locale);
-    return env->NewStringUTF(loc.getISO3Language());
+static jstring ICU_getISO3Language(JNIEnv* env, jclass, jstring javaLanguageTag) {
+  ScopedIcuLocale icuLocale(env, javaLanguageTag);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
+  return env->NewStringUTF(icuLocale.locale().getISO3Language());
 }
 
 static jobjectArray ICU_getISOCountriesNative(JNIEnv* env, jclass) {
@@ -568,7 +572,10 @@
         return JNI_FALSE; // ICU has a fixed-length limit.
     }
 
-    Locale locale = getLocale(env, javaLocaleName);
+    ScopedIcuLocale icuLocale(env, javaLocaleName);
+    if (!icuLocale.valid()) {
+      return JNI_FALSE;
+    }
 
     // Get the DateTimePatterns.
     UErrorCode status = U_ZERO_ERROR;
@@ -587,7 +594,7 @@
     // Get the "Yesterday", "Today", and "Tomorrow" strings.
     bool foundYesterdayTodayAndTomorrow = false;
     for (LocaleNameIterator it(localeName.c_str(), status); it.HasNext(); it.Up()) {
-      if (getYesterdayTodayAndTomorrow(env, localeData, locale, it.Get())) {
+      if (getYesterdayTodayAndTomorrow(env, localeData, icuLocale.locale(), it.Get())) {
         foundYesterdayTodayAndTomorrow = true;
         break;
       }
@@ -598,7 +605,7 @@
     }
 
     status = U_ZERO_ERROR;
-    UniquePtr<Calendar> cal(Calendar::createInstance(locale, status));
+    UniquePtr<Calendar> cal(Calendar::createInstance(icuLocale.locale(), status));
     if (U_FAILURE(status)) {
         return JNI_FALSE;
     }
@@ -608,7 +615,7 @@
 
     // Get DateFormatSymbols.
     status = U_ZERO_ERROR;
-    DateFormatSymbols dateFormatSym(locale, status);
+    DateFormatSymbols dateFormatSym(icuLocale.locale(), status);
     if (U_FAILURE(status)) {
         return JNI_FALSE;
     }
@@ -661,8 +668,8 @@
     status = U_ZERO_ERROR;
 
     // For numberPatterns and symbols.
-    setNumberPatterns(env, localeData, locale);
-    setDecimalFormatSymbolsData(env, localeData, locale);
+    setNumberPatterns(env, localeData, icuLocale.locale());
+    setDecimalFormatSymbolsData(env, localeData, icuLocale.locale());
 
     jstring countryCode = env->NewStringUTF(Locale::createFromName(localeName.c_str()).getCountry());
     jstring internationalCurrencySymbol = ICU_getCurrencyCode(env, NULL, countryCode);
@@ -685,25 +692,33 @@
     return JNI_TRUE;
 }
 
-static jstring ICU_toLowerCase(JNIEnv* env, jclass, jstring javaString, jstring localeName) {
+static jstring ICU_toLowerCase(JNIEnv* env, jclass, jstring javaString, jstring javaLanguageTag) {
   ScopedJavaUnicodeString scopedString(env, javaString);
   if (!scopedString.valid()) {
     return NULL;
   }
+  ScopedIcuLocale icuLocale(env, javaLanguageTag);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
   UnicodeString& s(scopedString.unicodeString());
   UnicodeString original(s);
-  s.toLower(getLocale(env, localeName));
+  s.toLower(icuLocale.locale());
   return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
 }
 
-static jstring ICU_toUpperCase(JNIEnv* env, jclass, jstring javaString, jstring localeName) {
+static jstring ICU_toUpperCase(JNIEnv* env, jclass, jstring javaString, jstring javaLanguageTag) {
   ScopedJavaUnicodeString scopedString(env, javaString);
   if (!scopedString.valid()) {
     return NULL;
   }
+  ScopedIcuLocale icuLocale(env, javaLanguageTag);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
   UnicodeString& s(scopedString.unicodeString());
   UnicodeString original(s);
-  s.toUpper(getLocale(env, localeName));
+  s.toUpper(icuLocale.locale());
   return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
 }
 
@@ -738,10 +753,14 @@
   return fromStringEnumeration(env, status, "ucurr_openISOCurrencies", &e);
 }
 
-static jstring ICU_getBestDateTimePatternNative(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName) {
-  Locale locale = getLocale(env, javaLocaleName);
+static jstring ICU_getBestDateTimePatternNative(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLanguageTag) {
+  ScopedIcuLocale icuLocale(env, javaLanguageTag);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
+
   UErrorCode status = U_ZERO_ERROR;
-  UniquePtr<DateTimePatternGenerator> generator(DateTimePatternGenerator::createInstance(locale, status));
+  UniquePtr<DateTimePatternGenerator> generator(DateTimePatternGenerator::createInstance(icuLocale.locale(), status));
   if (maybeThrowIcuException(env, "DateTimePatternGenerator::createInstance", status)) {
     return NULL;
   }
@@ -758,16 +777,14 @@
   return env->NewString(result.getBuffer(), result.length());
 }
 
-static void ICU_setDefaultLocale(JNIEnv* env, jclass, jstring javaLocaleName) {
-  Locale locale = getLocale(env, javaLocaleName);
-  UErrorCode status = U_ZERO_ERROR;
+static void ICU_setDefaultLocale(JNIEnv* env, jclass, jstring javaLanguageTag) {
+  ScopedIcuLocale icuLocale(env, javaLanguageTag);
+  if (!icuLocale.valid()) {
+    return;
+  }
 
-  // TODO: Should we check whether locale.isBogus() here ? ICU will
-  // accept bogus locales as the default without complaint. It
-  // shouldn't make a difference in practice, users that set a bogus
-  // locale as the default shouldn't have any realistic expectation that
-  // things like defaults etc. will work correctly.
-  Locale::setDefault(locale, status);
+  UErrorCode status = U_ZERO_ERROR;
+  Locale::setDefault(icuLocale.locale(), status);
   maybeThrowIcuException(env, "Locale::setDefault", status);
 }
 
@@ -796,14 +813,13 @@
     NATIVE_METHOD(ICU, getDisplayLanguageNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getDisplayScriptNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getDisplayVariantNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
-    NATIVE_METHOD(ICU, getISO3CountryNative, "(Ljava/lang/String;)Ljava/lang/String;"),
-    NATIVE_METHOD(ICU, getISO3LanguageNative, "(Ljava/lang/String;)Ljava/lang/String;"),
+    NATIVE_METHOD(ICU, getISO3Country, "(Ljava/lang/String;)Ljava/lang/String;"),
+    NATIVE_METHOD(ICU, getISO3Language, "(Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getISOCountriesNative, "()[Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getISOLanguagesNative, "()[Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getIcuVersion, "()Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getScript, "(Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(ICU, getUnicodeVersion, "()Ljava/lang/String;"),
-    NATIVE_METHOD(ICU, languageTagForLocale, "(Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(ICU, localeForLanguageTag, "(Ljava/lang/String;Z)Ljava/lang/String;"),
     NATIVE_METHOD(ICU, initLocaleDataNative, "(Ljava/lang/String;Llibcore/icu/LocaleData;)Z"),
     NATIVE_METHOD(ICU, setDefaultLocale, "(Ljava/lang/String;)V"),
diff --git a/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp b/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
index 0c8c3c9..ef0c2a9 100644
--- a/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
+++ b/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
@@ -20,6 +20,7 @@
 #include "JNIHelp.h"
 #include "JniConstants.h"
 #include "JniException.h"
+#include "ScopedIcuLocale.h"
 #include "ScopedUtfChars.h"
 #include "unicode/brkiter.h"
 #include "unicode/putil.h"
@@ -107,13 +108,12 @@
 };
 
 #define MAKE_BREAK_ITERATOR_INSTANCE(F) \
-  UErrorCode status = U_ZERO_ERROR; \
-  const ScopedUtfChars localeChars(env, javaLocale); \
-  if (localeChars.c_str() == NULL) { \
+  ScopedIcuLocale icuLocale(env, javaLocaleName); \
+  if (!icuLocale.valid()) { \
     return 0; \
   } \
-  Locale locale(Locale::createFromName(localeChars.c_str())); \
-  BreakIterator* it = F(locale, status); \
+  UErrorCode status = U_ZERO_ERROR; \
+  BreakIterator* it = F(icuLocale.locale(), status); \
   if (maybeThrowIcuException(env, "ubrk_open", status)) { \
     return 0; \
   } \
@@ -143,19 +143,19 @@
   return it->following(offset);
 }
 
-static jlong NativeBreakIterator_getCharacterInstanceImpl(JNIEnv* env, jclass, jstring javaLocale) {
+static jlong NativeBreakIterator_getCharacterInstanceImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
   MAKE_BREAK_ITERATOR_INSTANCE(BreakIterator::createCharacterInstance);
 }
 
-static jlong NativeBreakIterator_getLineInstanceImpl(JNIEnv* env, jclass, jstring javaLocale) {
+static jlong NativeBreakIterator_getLineInstanceImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
   MAKE_BREAK_ITERATOR_INSTANCE(BreakIterator::createLineInstance);
 }
 
-static jlong NativeBreakIterator_getSentenceInstanceImpl(JNIEnv* env, jclass, jstring javaLocale) {
+static jlong NativeBreakIterator_getSentenceInstanceImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
   MAKE_BREAK_ITERATOR_INSTANCE(BreakIterator::createSentenceInstance);
 }
 
-static jlong NativeBreakIterator_getWordInstanceImpl(JNIEnv* env, jclass, jstring javaLocale) {
+static jlong NativeBreakIterator_getWordInstanceImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
   MAKE_BREAK_ITERATOR_INSTANCE(BreakIterator::createWordInstance);
 }
 
diff --git a/luni/src/main/native/libcore_icu_NativeCollation.cpp b/luni/src/main/native/libcore_icu_NativeCollation.cpp
index 00ec9ae..4ce42ec 100644
--- a/luni/src/main/native/libcore_icu_NativeCollation.cpp
+++ b/luni/src/main/native/libcore_icu_NativeCollation.cpp
@@ -180,11 +180,12 @@
     return result;
 }
 
-static jlong NativeCollation_openCollator(JNIEnv* env, jclass, jstring localeName) {
-    ScopedUtfChars localeChars(env, localeName);
+static jlong NativeCollation_openCollator(JNIEnv* env, jclass, jstring javaLocaleName) {
+    ScopedUtfChars localeChars(env, javaLocaleName);
     if (localeChars.c_str() == NULL) {
         return 0;
     }
+
     UErrorCode status = U_ZERO_ERROR;
     UCollator* c = ucol_open(localeChars.c_str(), &status);
     maybeThrowIcuException(env, "ucol_open", status);
diff --git a/luni/src/main/native/libcore_icu_TimeZoneNames.cpp b/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
index ef1743e..faf87f1 100644
--- a/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
+++ b/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
@@ -20,6 +20,7 @@
 #include "JNIHelp.h"
 #include "JniConstants.h"
 #include "JniException.h"
+#include "ScopedIcuLocale.h"
 #include "ScopedJavaUnicodeString.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
@@ -59,11 +60,14 @@
   return true;
 }
 
-static void TimeZoneNames_fillZoneStrings(JNIEnv* env, jclass, jstring localeName, jobjectArray result) {
-  Locale locale = getLocale(env, localeName);
+static void TimeZoneNames_fillZoneStrings(JNIEnv* env, jclass, jstring javaLocaleName, jobjectArray result) {
+  ScopedIcuLocale icuLocale(env, javaLocaleName);
+  if (!icuLocale.valid()) {
+    return;
+  }
 
   UErrorCode status = U_ZERO_ERROR;
-  UniquePtr<TimeZoneNames> names(TimeZoneNames::createInstance(locale, status));
+  UniquePtr<TimeZoneNames> names(TimeZoneNames::createInstance(icuLocale.locale(), status));
   if (maybeThrowIcuException(env, "TimeZoneNames::createInstance", status)) {
     return;
   }
@@ -118,11 +122,14 @@
   }
 }
 
-static jstring TimeZoneNames_getExemplarLocation(JNIEnv* env, jclass, jstring javaLocale, jstring javaTz) {
-  Locale locale = getLocale(env, javaLocale);
+static jstring TimeZoneNames_getExemplarLocation(JNIEnv* env, jclass, jstring javaLocaleName, jstring javaTz) {
+  ScopedIcuLocale icuLocale(env, javaLocaleName);
+  if (!icuLocale.valid()) {
+    return NULL;
+  }
 
   UErrorCode status = U_ZERO_ERROR;
-  UniquePtr<TimeZoneNames> names(TimeZoneNames::createInstance(locale, status));
+  UniquePtr<TimeZoneNames> names(TimeZoneNames::createInstance(icuLocale.locale(), status));
   if (maybeThrowIcuException(env, "TimeZoneNames::createInstance", status)) {
     return NULL;
   }
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index c04f73e..2592fe7 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -44,9 +44,14 @@
 #include <stdlib.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
+#ifndef __APPLE__
 #include <sys/prctl.h>
+#endif
 #include <sys/socket.h>
 #include <sys/stat.h>
+#ifdef __APPLE__
+#include <sys/statvfs.h>
+#endif
 #include <sys/syscall.h>
 #include <sys/time.h>
 #include <sys/types.h>
@@ -56,6 +61,11 @@
 #include <termios.h>
 #include <unistd.h>
 
+
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
 #define TO_JAVA_STRING(NAME, EXP) \
         jstring NAME = env->NewStringUTF(EXP); \
         if (NAME == NULL) return NULL;
@@ -330,9 +340,14 @@
             static_cast<jlong>(tv.tv_sec), static_cast<jlong>(tv.tv_usec));
 }
 
-static jobject makeStructUcred(JNIEnv* env, const struct ucred& u) {
+static jobject makeStructUcred(JNIEnv* env, const struct ucred& u __unused) {
+#ifdef __APPLE__
+  jniThrowException(env, "java/lang/UnsupportedOperationException", "unimplemented support for ucred on a Mac");
+  return NULL;
+#else
   static jmethodID ctor = env->GetMethodID(JniConstants::structUcredClass, "<init>", "(III)V");
   return env->NewObject(JniConstants::structUcredClass, ctor, u.pid, u.uid, u.gid);
+#endif
 }
 
 static jobject makeStructUtsname(JNIEnv* env, const struct utsname& buf) {
@@ -847,9 +862,19 @@
   return makeStructUcred(env, u);
 }
 
-static jint Posix_gettid(JNIEnv*, jobject) {
+static jint Posix_gettid(JNIEnv* env __unused, jobject) {
+#if defined(__APPLE__)
+  uint64_t owner;
+  int rc = pthread_threadid_np(NULL, &owner);  // Requires Mac OS 10.6
+  if (rc != 0) {
+    throwErrnoException(env, "gettid");
+    return NULL;
+  }
+  return static_cast<jint>(owner);
+#else
   // Neither bionic nor glibc exposes gettid(2).
   return syscall(__NR_gettid);
+#endif
 }
 
 static jint Posix_getuid(JNIEnv*, jobject) {
@@ -1082,19 +1107,31 @@
     return rc;
 }
 
-static void Posix_posix_fallocate(JNIEnv* env, jobject, jobject javaFd, jlong offset, jlong length) {
+static void Posix_posix_fallocate(JNIEnv* env, jobject, jobject javaFd __unused,
+                                  jlong offset __unused, jlong length __unused) {
+#ifdef __APPLE__
+    jniThrowException(env, "java/lang/UnsupportedOperationException",
+                      "fallocate doesn't exist on a Mac");
+#else
     int fd = jniGetFDFromFileDescriptor(env, javaFd);
     errno = TEMP_FAILURE_RETRY(posix_fallocate64(fd, offset, length));
     if (errno != 0) {
         throwErrnoException(env, "posix_fallocate");
     }
+#endif
 }
 
-static jint Posix_prctl(JNIEnv* env, jobject, jint option, jlong arg2, jlong arg3, jlong arg4, jlong arg5) {
+static jint Posix_prctl(JNIEnv* env, jobject, jint option __unused, jlong arg2 __unused,
+                        jlong arg3 __unused, jlong arg4 __unused, jlong arg5 __unused) {
+#ifdef __APPLE__
+    jniThrowException(env, "java/lang/UnsupportedOperationException", "prctl doesn't exist on a Mac");
+    return 0;
+#else
     int result = prctl(static_cast<int>(option),
                        static_cast<unsigned long>(arg2), static_cast<unsigned long>(arg3),
                        static_cast<unsigned long>(arg4), static_cast<unsigned long>(arg5));
     return throwIfMinusOne(env, "prctl", result);
+#endif
 }
 
 static jint Posix_preadBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jlong offset) {
diff --git a/luni/src/test/java/libcore/android/system/OsConstantsTest.java b/luni/src/test/java/libcore/android/system/OsConstantsTest.java
new file mode 100644
index 0000000..681d68c
--- /dev/null
+++ b/luni/src/test/java/libcore/android/system/OsConstantsTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.system;
+
+import junit.framework.TestCase;
+
+public class OsConstantsTest extends TestCase {
+
+    // http://b/15602893
+    public void testBug15602893() {
+        assertTrue(OsConstants.RT_SCOPE_HOST > 0);
+        assertTrue(OsConstants.RT_SCOPE_LINK > 0);
+        assertTrue(OsConstants.RT_SCOPE_SITE > 0);
+
+        assertTrue(OsConstants.IFA_F_TENTATIVE > 0);
+    }
+}
diff --git a/luni/src/test/java/libcore/icu/ICUTest.java b/luni/src/test/java/libcore/icu/ICUTest.java
index 60ed0ca..3fa1f46 100644
--- a/luni/src/test/java/libcore/icu/ICUTest.java
+++ b/luni/src/test/java/libcore/icu/ICUTest.java
@@ -16,6 +16,8 @@
 
 package libcore.icu;
 
+import java.text.BreakIterator;
+import java.text.Collator;
 import java.util.Arrays;
 import java.util.Locale;
 
@@ -42,12 +44,12 @@
   }
 
   public void test_getBestDateTimePattern() throws Exception {
-    assertEquals("d MMMM", ICU.getBestDateTimePattern("MMMMd", "ca_ES"));
-    assertEquals("d 'de' MMMM", ICU.getBestDateTimePattern("MMMMd", "es_ES"));
-    assertEquals("d. MMMM", ICU.getBestDateTimePattern("MMMMd", "de_CH"));
-    assertEquals("MMMM d", ICU.getBestDateTimePattern("MMMMd", "en_US"));
-    assertEquals("d LLLL", ICU.getBestDateTimePattern("MMMMd", "fa_IR"));
-    assertEquals("M月d日", ICU.getBestDateTimePattern("MMMMd", "ja_JP"));
+    assertEquals("d MMMM", ICU.getBestDateTimePattern("MMMMd", new Locale("ca", "ES")));
+    assertEquals("d 'de' MMMM", ICU.getBestDateTimePattern("MMMMd", new Locale("es", "ES")));
+    assertEquals("d. MMMM", ICU.getBestDateTimePattern("MMMMd", new Locale("de", "CH")));
+    assertEquals("MMMM d", ICU.getBestDateTimePattern("MMMMd", new Locale("en", "US")));
+    assertEquals("d LLLL", ICU.getBestDateTimePattern("MMMMd", new Locale("fa", "IR")));
+    assertEquals("M月d日", ICU.getBestDateTimePattern("MMMMd", new Locale("ja", "JP")));
   }
 
   public void test_localeFromString() throws Exception {
@@ -73,7 +75,7 @@
   }
 
   private String best(Locale l, String skeleton) {
-    return ICU.getBestDateTimePattern(skeleton, l.toString());
+    return ICU.getBestDateTimePattern(skeleton, l);
   }
 
   public void test_getDateFormatOrder() throws Exception {
@@ -123,4 +125,130 @@
     } catch (IllegalArgumentException expected) {
     }
   }
+
+  public void testScriptsPassedToIcu() throws Exception {
+    Locale sr_Cyrl_BA = Locale.forLanguageTag("sr-Cyrl-BA");
+    Locale sr_Cyrl_ME = Locale.forLanguageTag("sr-Cyrl-ME");
+    Locale sr_Latn_BA = Locale.forLanguageTag("sr-Latn-BA");
+    Locale sr_Latn_ME = Locale.forLanguageTag("sr-Latn-ME");
+
+    assertEquals("sr_BA_#Cyrl", sr_Cyrl_BA.toString());
+    assertEquals("Cyrl",        sr_Cyrl_BA.getScript());
+
+    assertEquals("sr_ME_#Cyrl", sr_Cyrl_ME.toString());
+    assertEquals("Cyrl",        sr_Cyrl_ME.getScript());
+
+    assertEquals("sr_BA_#Latn", sr_Latn_BA.toString());
+    assertEquals("Latn",        sr_Latn_BA.getScript());
+
+    assertEquals("sr_ME_#Latn", sr_Latn_ME.toString());
+    assertEquals("Latn",        sr_Latn_ME.getScript());
+
+    assertEquals("Српски",              sr_Cyrl_BA.getDisplayLanguage(sr_Cyrl_BA));
+    assertEquals("Босна и Херцеговина", sr_Cyrl_BA.getDisplayCountry(sr_Cyrl_BA));
+    assertEquals("Ћирилица",            sr_Cyrl_BA.getDisplayScript(sr_Cyrl_BA));
+    assertEquals("",                    sr_Cyrl_BA.getDisplayVariant(sr_Cyrl_BA));
+
+    assertEquals("Српски",    sr_Cyrl_ME.getDisplayLanguage(sr_Cyrl_ME));
+    assertEquals("Црна Гора", sr_Cyrl_ME.getDisplayCountry(sr_Cyrl_ME));
+    assertEquals("Ћирилица",  sr_Cyrl_ME.getDisplayScript(sr_Cyrl_ME));
+    assertEquals("",          sr_Cyrl_ME.getDisplayVariant(sr_Cyrl_ME));
+
+    assertEquals("Srpski",              sr_Latn_BA.getDisplayLanguage(sr_Latn_BA));
+    assertEquals("Bosna i Hercegovina", sr_Latn_BA.getDisplayCountry(sr_Latn_BA));
+    assertEquals("Latinica",            sr_Latn_BA.getDisplayScript(sr_Latn_BA));
+    assertEquals("",                    sr_Latn_BA.getDisplayVariant(sr_Latn_BA));
+
+    assertEquals("Srpski",    sr_Latn_ME.getDisplayLanguage(sr_Latn_ME));
+    assertEquals("Crna Gora", sr_Latn_ME.getDisplayCountry(sr_Latn_ME));
+    assertEquals("Latinica",  sr_Latn_ME.getDisplayScript(sr_Latn_ME));
+    assertEquals("",          sr_Latn_ME.getDisplayVariant(sr_Latn_ME));
+
+    assertEquals("BIH", sr_Cyrl_BA.getISO3Country());
+    assertEquals("srp", sr_Cyrl_BA.getISO3Language());
+    assertEquals("MNE", sr_Cyrl_ME.getISO3Country());
+    assertEquals("srp", sr_Cyrl_ME.getISO3Language());
+    assertEquals("BIH", sr_Latn_BA.getISO3Country());
+    assertEquals("srp", sr_Latn_BA.getISO3Language());
+    assertEquals("MNE", sr_Latn_ME.getISO3Country());
+    assertEquals("srp", sr_Latn_ME.getISO3Language());
+
+    BreakIterator.getCharacterInstance(sr_Cyrl_BA);
+    BreakIterator.getCharacterInstance(sr_Cyrl_ME);
+    BreakIterator.getCharacterInstance(sr_Latn_BA);
+    BreakIterator.getCharacterInstance(sr_Latn_ME);
+
+    BreakIterator.getLineInstance(sr_Cyrl_BA);
+    BreakIterator.getLineInstance(sr_Cyrl_ME);
+    BreakIterator.getLineInstance(sr_Latn_BA);
+    BreakIterator.getLineInstance(sr_Latn_ME);
+
+    BreakIterator.getSentenceInstance(sr_Cyrl_BA);
+    BreakIterator.getSentenceInstance(sr_Cyrl_ME);
+    BreakIterator.getSentenceInstance(sr_Latn_BA);
+    BreakIterator.getSentenceInstance(sr_Latn_ME);
+
+    BreakIterator.getWordInstance(sr_Cyrl_BA);
+    BreakIterator.getWordInstance(sr_Cyrl_ME);
+    BreakIterator.getWordInstance(sr_Latn_BA);
+    BreakIterator.getWordInstance(sr_Latn_ME);
+
+    Collator.getInstance(sr_Cyrl_BA);
+    Collator.getInstance(sr_Cyrl_ME);
+    Collator.getInstance(sr_Latn_BA);
+    Collator.getInstance(sr_Latn_ME);
+
+    // TODO: This needs to be fixed. We shouldn't output attribute key
+    // expansions in the language tag or the toString output. The tests
+    // will fail with something like:
+    //
+    // expected:<de-u-co[-phonebk-kf-upper-kn]> but was:
+    // <de-u-co[lcasefirst-upper-collation-phonebook-colnumeric-yes]>
+    Locale l = Locale.forLanguageTag("de-u-co-phonebk-kf-upper-kn");
+    assertEquals("de__#u-co-phonebk-kf-upper-kn", l.toString());
+    assertEquals("de-u-co-phonebk-kf-upper-kn", l.toLanguageTag());
+
+    Collator c = Collator.getInstance(l);
+    assertTrue(c.compare("2", "11") < 0);
+    assertTrue(c.compare("11", "ae") < 0);
+    assertTrue(c.compare("ae", "Ä") < 0);
+    assertTrue(c.compare("Ä", "ä") < 0);
+    assertTrue(c.compare("ä", "AF") < 0);
+    assertTrue(c.compare("AF", "af") < 0);
+  }
+
+  // Test for the behavior of currency symbol lookup when an unrecognized locale has been set as the
+  // default.
+  public void testIcuDefaultAffectsCurrencySymbol() {
+    // A locale that is not going to be recognized by ICU and should fallback to "root" for the
+    // currency symbol.
+    final Locale unrecognizedLocale = new Locale("xy", "KR");
+
+    // A known locale with a relatively stable representation for its currency symbol.
+    final Locale enUsLocale = new Locale("en", "US");
+    final String usDollar = "USD";
+
+    String initialDefaultLocale = ICU.getDefaultLocale();
+    try {
+      // Confirm the "$" symbol for USD in en-US.
+      assertEquals("$", ICU.getCurrencySymbol(enUsLocale, usDollar));
+
+      // Set the default so this will be used as fallback for the unrecognized locale symbol lookup.
+      ICU.setDefaultLocale(enUsLocale.toLanguageTag());
+
+      // Demonstrate the USD symbol is reported as "$" for the unrecognized locale (which is using
+      // the default).
+      assertEquals("$", ICU.getCurrencySymbol(unrecognizedLocale, usDollar));
+
+      // Change the default.
+      ICU.setDefaultLocale(unrecognizedLocale.toLanguageTag());
+
+      String currencySymbolAfterDefaultChange = ICU.getCurrencySymbol(unrecognizedLocale, usDollar);
+      // "$US" is the value from root. With an unrecognized locale argument, and an unrecognized
+      // locale as the default, ICU has returns the value in root.
+      assertEquals("US$", currencySymbolAfterDefaultChange);
+    } finally {
+      ICU.setDefaultLocale(initialDefaultLocale);
+    }
+  }
 }
diff --git a/luni/src/test/java/libcore/java/lang/OldRuntimeTest.java b/luni/src/test/java/libcore/java/lang/OldRuntimeTest.java
index 0926569..294cea2 100644
--- a/luni/src/test/java/libcore/java/lang/OldRuntimeTest.java
+++ b/luni/src/test/java/libcore/java/lang/OldRuntimeTest.java
@@ -34,28 +34,6 @@
 
     InputStream is;
 
-    public void test_freeMemory() {
-        // Heap might grow or do GC at any time,
-        // so we can't really test a lot. Hence
-        // we are just doing some basic sanity
-        // checks here.
-        assertTrue("must have some free memory",
-                r.freeMemory() > 0);
-
-        assertTrue("must not exceed total memory",
-                r.freeMemory() < r.totalMemory());
-
-        long before = r.totalMemory() - r.freeMemory();
-        Vector<byte[]> v = new Vector<byte[]>();
-        for (int i = 1; i < 10; i++) {
-            v.addElement(new byte[10000]);
-        }
-        long after =  r.totalMemory() - r.freeMemory();
-
-        assertTrue("free memory must change with allocations",
-                after != before);
-    }
-
     public void test_getRuntime() {
         // Test for method java.lang.Runtime java.lang.Runtime.getRuntime()
         assertNotNull(Runtime.getRuntime());
@@ -451,10 +429,6 @@
         }
     }
 
-    public void test_maxMemory() {
-        assertTrue(Runtime.getRuntime().maxMemory() < Long.MAX_VALUE);
-    }
-
     public void test_traceInstructions() {
         Runtime.getRuntime().traceInstructions(false);
         Runtime.getRuntime().traceInstructions(true);
diff --git a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
index a7eac3a..f0db3ba 100644
--- a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
@@ -19,6 +19,7 @@
 import java.nio.channels.MembershipKey;
 import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.List;
 
 /**
  * Tests associated with multicast behavior of DatagramChannel.
@@ -34,8 +35,8 @@
   }
 
   // These IP addresses aren't inherently "good" or "bad"; they're just used like that.
-  // We use the "good" addresses for our actual group, and the "bad" addresses are for
-  // a group that we won't actually set up.
+  // We use the "good" addresses for our actual group, and the "bad" addresses are for a group that
+  // we won't actually set up.
   private static final InetAddress GOOD_MULTICAST_IPv4 = lookup("239.255.0.1");
   private static final InetAddress BAD_MULTICAST_IPv4 = lookup("239.255.0.2");
   private static final InetAddress GOOD_MULTICAST_IPv6 = lookup("ff05::7:7");
@@ -52,54 +53,44 @@
   private static final InetAddress UNICAST_IPv6_1 = lookup("2001:db8::1");
   private static final InetAddress UNICAST_IPv6_2 = lookup("2001:db8::2");
 
-  private NetworkInterface networkInterface1;
-  private NetworkInterface IPV6networkInterface1;
+  private List<NetworkInterface> ipv4networkInterfaces = new ArrayList<NetworkInterface>();
+  private List<NetworkInterface> ipv6networkInterfaces = new ArrayList<NetworkInterface>();
+  private NetworkInterface ipv4networkInterface;
+  private NetworkInterface ipv6networkInterface;
   private NetworkInterface loopbackInterface;
 
   @Override
   protected void setUp() throws Exception {
-    // The loopback interface isn't actually useful for sending/receiving multicast messages
-    // but it can be used as a dummy for tests where that does not matter.
+    // The loopback interface isn't actually useful for sending/receiving multicast messages but it
+    // can be used as a dummy for tests where that does not matter.
     loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
     assertNotNull(loopbackInterface);
     assertTrue(loopbackInterface.isLoopback());
     assertFalse(loopbackInterface.supportsMulticast());
 
     Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
-
-    // only consider interfaces that have addresses associated with them.
-    // Otherwise tests don't work so well
-    if (interfaces != null) {
-      boolean atLeastOneInterface = false;
-      while (interfaces.hasMoreElements() && (atLeastOneInterface == false)) {
-        networkInterface1 = interfaces.nextElement();
-        if (willWorkForMulticast(networkInterface1)) {
-          atLeastOneInterface = true;
-        }
-      }
-
-      assertTrue("Test environment must have at least one network interface capable of multicast",
-              atLeastOneInterface);
-
-      // Find the first multicast-compatible interface that supports IPV6 if one exists
-      interfaces = NetworkInterface.getNetworkInterfaces();
-
-      boolean found = false;
-      while (interfaces.hasMoreElements() && !found) {
-        NetworkInterface nextInterface = interfaces.nextElement();
-        if (willWorkForMulticast(nextInterface)) {
-          Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
-          while (addresses.hasMoreElements()) {
-            final InetAddress nextAddress = addresses.nextElement();
-            if (nextAddress instanceof Inet6Address) {
-              IPV6networkInterface1 = nextInterface;
-              found = true;
-              break;
-            }
+    assertNotNull(interfaces);
+    // Only consider interfaces that have addresses associated with them. Otherwise tests don't work
+    // so well.
+    while (interfaces.hasMoreElements()) {
+      NetworkInterface networkInterface = interfaces.nextElement();
+      if (willWorkForMulticast(networkInterface)) {
+        Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
+        while (addresses.hasMoreElements()) {
+          final InetAddress nextAddress = addresses.nextElement();
+          if (nextAddress instanceof Inet4Address) {
+            ipv4networkInterfaces.add(networkInterface);
+          } else if (nextAddress instanceof Inet6Address) {
+            ipv6networkInterfaces.add(networkInterface);
           }
         }
       }
     }
+    assertTrue(
+        "Test environment must have network interfaces capable of both IPv4 and IPv6 multicast",
+        ipv4networkInterfaces.size() > 0 && ipv6networkInterfaces.size() > 0);
+    ipv4networkInterface = ipv4networkInterfaces.get(0);
+    ipv6networkInterface = ipv6networkInterfaces.get(0);
   }
 
   public void test_open() throws IOException {
@@ -108,9 +99,15 @@
     // Unlike MulticastSocket, DatagramChannel has SO_REUSEADDR set to false by default.
     assertFalse(dc.getOption(StandardSocketOptions.SO_REUSEADDR));
 
+    // Confirm multicast loop is on by default as specified in the docs. Many tests in this class
+    // depend on this being true.
+    assertTrue(dc.getOption(StandardSocketOptions.IP_MULTICAST_LOOP));
+
     assertNull(dc.getLocalAddress());
     assertTrue(dc.isOpen());
     assertFalse(dc.isConnected());
+
+    dc.close();
   }
 
   public void test_bind_null() throws Exception {
@@ -133,7 +130,7 @@
     DatagramChannel dc = createReceiverChannel();
     dc.close();
     try {
-      dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+      dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface);
       fail();
     } catch (ClosedChannelException expected) {
     }
@@ -142,7 +139,7 @@
   public void test_joinAnySource_nullGroupAddress() throws Exception {
     DatagramChannel dc = createReceiverChannel();
     try {
-      dc.join(null, networkInterface1);
+      dc.join(null, ipv4networkInterface);
       fail();
     } catch (NullPointerException expected) {
     }
@@ -160,19 +157,22 @@
   }
 
   public void test_joinAnySource_nonMulticastGroupAddress_IPv4() throws Exception {
-    DatagramChannel dc = createReceiverChannel();
-    try {
-      dc.join(UNICAST_IPv4_1, networkInterface1);
-      fail();
-    } catch (IllegalArgumentException expected) {
+    for (NetworkInterface networkInterface : ipv4networkInterfaces) {
+      test_joinAnySource_illegalArgumentExpected(networkInterface, UNICAST_IPv4_1);
     }
-    dc.close();
   }
 
   public void test_joinAnySource_nonMulticastGroupAddress_IPv6() throws Exception {
+    for (NetworkInterface networkInterface : ipv6networkInterfaces) {
+      test_joinAnySource_illegalArgumentExpected(networkInterface, UNICAST_IPv6_1);
+    }
+  }
+
+  private void test_joinAnySource_illegalArgumentExpected(NetworkInterface networkInterface,
+      InetAddress group) throws Exception {
     DatagramChannel dc = createReceiverChannel();
     try {
-      dc.join(UNICAST_IPv6_1, networkInterface1);
+      dc.join(group, networkInterface);
       fail();
     } catch (IllegalArgumentException expected) {
     }
@@ -180,36 +180,42 @@
   }
 
   public void test_joinAnySource_IPv4() throws Exception {
-    test_joinAnySource(GOOD_MULTICAST_IPv4, BAD_MULTICAST_IPv4);
+    test_joinAnySource(ipv4networkInterfaces, GOOD_MULTICAST_IPv4, BAD_MULTICAST_IPv4);
   }
 
   public void test_joinAnySource_IPv6() throws Exception {
-    test_joinAnySource(GOOD_MULTICAST_IPv6, BAD_MULTICAST_IPv6);
+    test_joinAnySource(ipv6networkInterfaces, GOOD_MULTICAST_IPv6, BAD_MULTICAST_IPv6);
   }
 
-  private void test_joinAnySource(InetAddress group, InetAddress group2) throws Exception {
-    // Set up a receiver join the group on networkInterface1
-    DatagramChannel receiverChannel = createReceiverChannel();
-    InetSocketAddress localAddress = (InetSocketAddress) receiverChannel.getLocalAddress();
-    receiverChannel.join(group, networkInterface1);
+  private void test_joinAnySource(
+      Iterable<NetworkInterface> networkInterfaces, InetAddress group, InetAddress group2)
+      throws Exception {
+    for (NetworkInterface networkInterface : networkInterfaces) {
+      // Set up a receiver join the group on networkInterface.
+      DatagramChannel receiverChannel = createReceiverChannel();
+      InetSocketAddress localAddress = (InetSocketAddress) receiverChannel.getLocalAddress();
+      receiverChannel.join(group, networkInterface);
 
-    String msg = "Hello World";
-    sendMulticastMessage(group, localAddress.getPort(), msg);
+      // Send a message to the group we joined.
+      String msg = "Hello World";
+      sendMessage(group, localAddress.getPort(), msg, networkInterface);
 
-    // now verify that we received the data as expected
-    ByteBuffer recvBuffer = ByteBuffer.allocate(100);
-    SocketAddress sourceAddress = receiverChannel.receive(recvBuffer);
-    assertNotNull(sourceAddress);
-    assertEquals(msg, new String(recvBuffer.array(), 0, recvBuffer.position()));
+      // Now verify that we received the data as expected.
+      ByteBuffer recvBuffer = ByteBuffer.allocate(100);
+      SocketAddress sourceAddress = receiverChannel.receive(recvBuffer);
+      assertNotNull(sourceAddress);
+      assertEquals(msg, new String(recvBuffer.array(), 0, recvBuffer.position()));
 
-    // now verify that we didn't receive the second message
-    String msg2 = "Hello World - Different Group";
-    sendMulticastMessage(group2, localAddress.getPort(), msg2);
-    recvBuffer.position(0);
-    SocketAddress sourceAddress2 = receiverChannel.receive(recvBuffer);
-    assertNull(sourceAddress2);
+      // Send a message to the group we did not join.
+      String msg2 = "Hello World - Different Group";
+      sendMessage(group2, localAddress.getPort(), msg2, networkInterface);
+      recvBuffer.position(0);
+      // Now verify that we didn't receive the second message.
+      SocketAddress sourceAddress2 = receiverChannel.receive(recvBuffer);
+      assertNull(sourceAddress2);
 
-    receiverChannel.close();
+      receiverChannel.close();
+    }
   }
 
   public void test_joinAnySource_processLimit() throws Exception {
@@ -217,11 +223,11 @@
     for (byte i = 1; i <= 25; i++) {
       InetAddress groupAddress = Inet4Address.getByName("239.255.0." + i);
       try {
-        dc.join(groupAddress, networkInterface1);
+        dc.join(groupAddress, ipv4networkInterface);
       } catch (SocketException e) {
         // There is a limit, that's ok according to the RI docs. For this test a lower bound of 20
         // is used, which appears to be the default linux limit.
-        // See /proc/sys/net/ipv4/igmp_max_memberships
+        // See /proc/sys/net/ipv4/igmp_max_memberships.
         assertTrue(i > 20);
         break;
       }
@@ -232,7 +238,7 @@
 
   public void test_joinAnySource_blockLimit() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey key = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+    MembershipKey key = dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface);
     for (byte i = 1; i <= 15; i++) {
       InetAddress sourceAddress = Inet4Address.getByName("10.0.0." + i);
       try {
@@ -240,7 +246,7 @@
       } catch (SocketException e) {
         // There is a limit, that's ok according to the RI docs. For this test a lower bound of 10
         // is used, which appears to be the default linux limit.
-        // See /proc/sys/net/ipv4/igmp_max_msf
+        // See /proc/sys/net/ipv4/igmp_max_msf.
         assertTrue(i > 10);
         break;
       }
@@ -250,12 +256,22 @@
   }
 
   /** Confirms that calling join() does not cause an implicit bind() to take place. */
-  public void test_joinAnySource_doesNotCauseBind() throws Exception {
-    DatagramChannel dc = DatagramChannel.open();
-    dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
-    assertNull(dc.getLocalAddress());
+  public void test_joinAnySource_doesNotCauseBind_IPv4() throws Exception {
+    test_joinAnySource_doesNotCauseBind(ipv4networkInterfaces, GOOD_MULTICAST_IPv4);
+  }
 
-    dc.close();
+  public void test_joinAnySource_doesNotCauseBind_IPv6() throws Exception {
+    test_joinAnySource_doesNotCauseBind(ipv6networkInterfaces, GOOD_MULTICAST_IPv6);
+  }
+
+  private void test_joinAnySource_doesNotCauseBind(
+      Iterable<NetworkInterface> networkInterfaces, InetAddress group) throws IOException {
+    for (NetworkInterface networkInterface : networkInterfaces) {
+      DatagramChannel dc = DatagramChannel.open();
+      dc.join(group, networkInterface);
+      assertNull(dc.getLocalAddress());
+      dc.close();
+    }
   }
 
   public void test_joinAnySource_networkInterfaces() throws Exception {
@@ -267,191 +283,192 @@
     Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
     while (theInterfaces.hasMoreElements()) {
       NetworkInterface thisInterface = theInterfaces.nextElement();
-      if (thisInterface.getInetAddresses().hasMoreElements()) {
+      // Skip interfaces that do not support multicast - there's no point in proving they cannot
+      // send / receive multicast messages.
+      if (willWorkForMulticast(thisInterface)) {
         realInterfaces.add(thisInterface);
       }
     }
 
-    for (int i = 0; i < realInterfaces.size(); i++) {
-      NetworkInterface thisInterface = realInterfaces.get(i);
-      if (!thisInterface.supportsMulticast()) {
-        // Skip interfaces that do not support multicast - there's no point in proving
-        // they cannot send / receive multicast messages.
-        continue;
-      }
-
-      // get the first address on the interface
-
-      // start server which is joined to the group and has
-      // only asked for packets on this interface
+    for (NetworkInterface thisInterface : realInterfaces) {
+      // Get the first address on the interface.
       Enumeration<InetAddress> addresses = thisInterface.getInetAddresses();
 
-      NetworkInterface sendingInterface = null;
-      InetAddress group = null;
-      if (addresses.hasMoreElements()) {
-        InetAddress firstAddress = addresses.nextElement();
-        if (firstAddress instanceof Inet4Address) {
+      while (addresses.hasMoreElements()) {
+        InetAddress listenAddress = addresses.nextElement();
+
+        // Start a server which is joined to the group and has only asked for packets on this
+        // interface.
+        NetworkInterface sendingInterface;
+        InetAddress group;
+        if (listenAddress instanceof Inet4Address) {
           group = GOOD_MULTICAST_IPv4;
-          sendingInterface = networkInterface1;
+          sendingInterface = ipv4networkInterface;
         } else {
-          // if this interface only seems to support IPV6 addresses
           group = GOOD_MULTICAST_IPv6;
-          sendingInterface = IPV6networkInterface1;
+          sendingInterface = ipv6networkInterface;
         }
+        DatagramChannel dc = createReceiverChannel();
+        InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress();
+        dc.join(group, thisInterface);
+
+        // Now send out a packet on sendingInterface. We should only see the packet if we send
+        // it on the same interface we are listening on (thisInterface).
+        String msg = "Hello World - Again " + thisInterface.getName();
+        sendMessage(group, localAddress.getPort(), msg, sendingInterface);
+
+        ByteBuffer recvBuffer = ByteBuffer.allocate(100);
+        SocketAddress sourceAddress = dc.receive(recvBuffer);
+        if (thisInterface.equals(sendingInterface)) {
+          assertEquals(msg, new String(recvBuffer.array(), 0, recvBuffer.position()));
+        } else {
+          assertNull(sourceAddress);
+        }
+
+        dc.close();
       }
-
-      DatagramChannel dc = createReceiverChannel();
-      InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress();
-      dc.join(group, thisInterface);
-
-      // Now send out a package on sendingInterface. We should only see the packet if we send
-      // it on the same interface we are listening on (thisInterface).
-      String msg = "Hello World - Again" + thisInterface.getName();
-      sendMulticastMessage(group, localAddress.getPort(), msg, sendingInterface);
-
-      ByteBuffer recvBuffer = ByteBuffer.allocate(100);
-      SocketAddress sourceAddress = dc.receive(recvBuffer);
-      if (thisInterface.equals(sendingInterface)) {
-        assertEquals(msg, new String(recvBuffer.array(), 0, recvBuffer.position()));
-      } else {
-        assertNull(sourceAddress);
-      }
-
-      dc.close();
     }
   }
 
   /** Confirms that the scope of each membership is network interface-level. */
-  public void test_join_canMixTypesOnDifferentInterfaces() throws Exception {
+  public void test_join_canMixJoinTypesOnDifferentInterfaces() throws Exception {
     DatagramChannel dc = DatagramChannel.open();
-    MembershipKey membershipKey1 = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+    MembershipKey membershipKey1 = dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface);
     MembershipKey membershipKey2 = dc.join(GOOD_MULTICAST_IPv4, loopbackInterface, UNICAST_IPv4_1);
     assertNotSame(membershipKey1, membershipKey2);
 
     dc.close();
   }
 
-
-  private DatagramChannel createReceiverChannel() throws Exception {
-    DatagramChannel dc = DatagramChannel.open();
-    dc.bind(null /* leave the OS to determine the port, and use the wildcard address */);
-    configureChannelForReceiving(dc);
-    return dc;
-  }
-
   public void test_joinAnySource_multiple_joins_IPv4()
       throws Exception {
-    test_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv4);
+    test_joinAnySource_multiple_joins(ipv4networkInterfaces, GOOD_MULTICAST_IPv4);
   }
 
   public void test_joinAnySource_multiple_joins_IPv6()
       throws Exception {
-    test_joinAnySource_multiple_joins(GOOD_MULTICAST_IPv6);
+    test_joinAnySource_multiple_joins(ipv6networkInterfaces, GOOD_MULTICAST_IPv6);
   }
 
-  private void test_joinAnySource_multiple_joins(InetAddress group) throws Exception {
-    DatagramChannel dc = createReceiverChannel();
+  private void test_joinAnySource_multiple_joins(
+      Iterable<NetworkInterface> networkInterfaces, InetAddress group) throws Exception {
+    for (NetworkInterface networkInterface : networkInterfaces) {
+      DatagramChannel dc = createReceiverChannel();
 
-    MembershipKey membershipKey1 = dc.join(group, networkInterface1);
+      MembershipKey membershipKey1 = dc.join(group, networkInterface);
 
-    MembershipKey membershipKey2 = dc.join(group, loopbackInterface);
-    assertFalse(membershipKey1.equals(membershipKey2));
+      MembershipKey membershipKey2 = dc.join(group, loopbackInterface);
+      assertFalse(membershipKey1.equals(membershipKey2));
 
-    MembershipKey membershipKey1_2 = dc.join(group, networkInterface1);
-    assertEquals(membershipKey1, membershipKey1_2);
+      MembershipKey membershipKey1_2 = dc.join(group, networkInterface);
+      assertEquals(membershipKey1, membershipKey1_2);
 
-    dc.close();
+      dc.close();
+    }
   }
 
   public void test_joinAnySource_multicastLoopOption_IPv4() throws Exception {
-    test_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv4);
+    test_joinAnySource_multicastLoopOption(ipv4networkInterfaces, GOOD_MULTICAST_IPv4);
   }
 
-  public void test_multicastLoopOption_IPv6() throws Exception {
-    test_joinAnySource_multicastLoopOption(GOOD_MULTICAST_IPv6);
+  public void test_joinAnySource_multicastLoopOption_IPv6() throws Exception {
+    test_joinAnySource_multicastLoopOption(ipv6networkInterfaces, GOOD_MULTICAST_IPv6);
   }
 
-  private void test_joinAnySource_multicastLoopOption(InetAddress group) throws Exception {
+  private void test_joinAnySource_multicastLoopOption(
+      Iterable<NetworkInterface> networkInterfaces, InetAddress group) throws Exception {
     final String message = "Hello, world!";
 
-    DatagramChannel dc = createReceiverChannel();
-    dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true /* enable loop */);
-    configureChannelForReceiving(dc);
-    dc.join(group, networkInterface1);
+    for (NetworkInterface networkInterface : networkInterfaces) {
+      DatagramChannel dc = DatagramChannel.open();
+      configureChannelForReceiving(dc);
+      dc.bind(null /* leave the OS to determine the port, and use the wildcard address */);
 
-    InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress();
+      // Make sure that the sent packets will be sent via the interface we will be joining with.
+      dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface);
+      dc.join(group, networkInterface);
 
-    // send the datagram
-    byte[] sendData = message.getBytes();
-    ByteBuffer sendBuffer = ByteBuffer.wrap(sendData);
-    dc.send(sendBuffer, new InetSocketAddress(group, localAddress.getPort()));
+      // Test with loop on.
+      dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true /* enable loop */);
 
-    // receive the datagram
-    ByteBuffer recvBuffer = ByteBuffer.allocate(100);
-    SocketAddress sourceAddress = dc.receive(recvBuffer);
-    assertNotNull(sourceAddress);
+      InetSocketAddress localAddress = (InetSocketAddress) dc.getLocalAddress();
 
-    String recvMessage = new String(recvBuffer.array(), 0, recvBuffer.position());
-    assertEquals(message, recvMessage);
+      // Send the datagram.
+      sendMessage(dc, message, new InetSocketAddress(group, localAddress.getPort()));
 
-    // Turn off loop
-    dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false /* enable loopback */);
+      // Receive the datagram.
+      ByteBuffer recvBuffer = ByteBuffer.allocate(100);
+      SocketAddress sourceAddress = dc.receive(recvBuffer);
+      assertNotNull(sourceAddress);
 
-    // send another datagram
-    recvBuffer.position(0);
-    ByteBuffer sendBuffer2 = ByteBuffer.wrap(sendData);
-    dc.send(sendBuffer2, new InetSocketAddress(group, localAddress.getPort()));
+      String recvMessage = new String(recvBuffer.array(), 0, recvBuffer.position());
+      assertEquals(message, recvMessage);
 
-    SocketAddress sourceAddress2 = dc.receive(recvBuffer);
-    assertNull(sourceAddress2);
+      // Turn off loop.
+      dc.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false /* enable loopback */);
 
-    dc.close();
+      // Send another datagram.
+      recvBuffer.position(0);
+      sendMessage(dc, message, new InetSocketAddress(group, localAddress.getPort()));
+
+      SocketAddress sourceAddress2 = dc.receive(recvBuffer);
+      assertNull(sourceAddress2);
+
+      dc.close();
+    }
   }
 
   public void testMembershipKeyAccessors_IPv4() throws Exception {
-    testMembershipKeyAccessors(GOOD_MULTICAST_IPv4);
+    testMembershipKeyAccessors(ipv4networkInterfaces, GOOD_MULTICAST_IPv4);
   }
 
   public void testMembershipKeyAccessors_IPv6() throws Exception {
-    testMembershipKeyAccessors(GOOD_MULTICAST_IPv6);
+    testMembershipKeyAccessors(ipv6networkInterfaces, GOOD_MULTICAST_IPv6);
   }
 
-  private void testMembershipKeyAccessors(InetAddress group) throws Exception {
-    DatagramChannel dc = createReceiverChannel();
+  private void testMembershipKeyAccessors(
+      Iterable<NetworkInterface> networkInterfaces, InetAddress group) throws Exception {
+    for (NetworkInterface networkInterface : networkInterfaces) {
+      DatagramChannel dc = createReceiverChannel();
 
-    MembershipKey key = dc.join(group, networkInterface1);
-    assertSame(dc, key.channel());
-    assertSame(group, key.group());
-    assertTrue(key.isValid());
-    assertSame(networkInterface1, key.networkInterface());
-    assertNull(key.sourceAddress());
+      MembershipKey key = dc.join(group, networkInterface);
+      assertSame(dc, key.channel());
+      assertSame(group, key.group());
+      assertTrue(key.isValid());
+      assertSame(networkInterface, key.networkInterface());
+      assertNull(key.sourceAddress());
+    }
   }
 
   public void test_dropAnySource_twice_IPv4() throws Exception {
-    test_dropAnySource_twice(GOOD_MULTICAST_IPv4);
+    test_dropAnySource_twice(ipv4networkInterfaces, GOOD_MULTICAST_IPv4);
   }
 
   public void test_dropAnySource_twice_IPv6() throws Exception {
-    test_dropAnySource_twice(GOOD_MULTICAST_IPv6);
+    test_dropAnySource_twice(ipv6networkInterfaces, GOOD_MULTICAST_IPv6);
   }
 
-  private void test_dropAnySource_twice(InetAddress group) throws Exception {
-    DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(group, networkInterface1);
+  private void test_dropAnySource_twice(
+      Iterable<NetworkInterface> networkInterfaces, InetAddress group)
+      throws Exception {
+    for (NetworkInterface networkInterface : networkInterfaces) {
+      DatagramChannel dc = createReceiverChannel();
+      MembershipKey membershipKey = dc.join(group, networkInterface);
 
-    assertTrue(membershipKey.isValid());
-    membershipKey.drop();
-    assertFalse(membershipKey.isValid());
+      assertTrue(membershipKey.isValid());
+      membershipKey.drop();
+      assertFalse(membershipKey.isValid());
 
-    // Try to leave a group we are no longer a member of - should do nothing.
-    membershipKey.drop();
+      // Try to leave a group we are no longer a member of. It should do nothing.
+      membershipKey.drop();
 
-    dc.close();
+      dc.close();
+    }
   }
 
   public void test_close_invalidatesMembershipKey() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface);
 
     assertTrue(membershipKey.isValid());
 
@@ -462,7 +479,7 @@
 
   public void test_block_null() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface);
     try {
       membershipKey.block(null);
       fail();
@@ -473,32 +490,34 @@
   }
 
   public void test_block_mixedAddressTypes_IPv4() throws Exception {
-    DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
-    try {
-      membershipKey.block(UNICAST_IPv6_1);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-
-    dc.close();
+    test_block_illegalArgument(ipv4networkInterfaces, GOOD_MULTICAST_IPv4, UNICAST_IPv6_1);
   }
 
   public void test_block_mixedAddressTypes_IPv6() throws Exception {
-    DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, networkInterface1);
-    try {
-      membershipKey.block(UNICAST_IPv4_1);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
+    test_block_illegalArgument(ipv6networkInterfaces, GOOD_MULTICAST_IPv6, UNICAST_IPv4_1);
+  }
 
-    dc.close();
+  private void test_block_illegalArgument(
+      Iterable<NetworkInterface> networkInterfaces, InetAddress groupAddress,
+      InetAddress badBlockAddress) throws Exception {
+
+    for (NetworkInterface networkInterface : networkInterfaces) {
+      DatagramChannel dc = createReceiverChannel();
+      MembershipKey membershipKey = dc.join(groupAddress, networkInterface);
+      try {
+        membershipKey.block(badBlockAddress);
+        fail();
+      } catch (IllegalArgumentException expected) {
+      }
+
+      dc.close();
+    }
   }
 
   public void test_block_cannotBlockWithSourceSpecificMembership() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1, UNICAST_IPv4_1);
+    MembershipKey membershipKey =
+        dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface, UNICAST_IPv4_1);
     try {
       membershipKey.block(UNICAST_IPv4_2);
       fail();
@@ -510,7 +529,7 @@
 
   public void test_block_multipleBlocksIgnored() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface);
     membershipKey.block(UNICAST_IPv4_1);
 
     MembershipKey membershipKey2 = membershipKey.block(UNICAST_IPv4_1);
@@ -521,7 +540,7 @@
 
   public void test_block_wildcardAddress() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface);
     try {
       membershipKey.block(WILDCARD_IPv4);
       fail();
@@ -533,7 +552,7 @@
 
   public void test_unblock_multipleUnblocksFail() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface);
 
     try {
       membershipKey.unblock(UNICAST_IPv4_1);
@@ -557,16 +576,16 @@
 
   public void test_unblock_null() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface);
     membershipKey.block(UNICAST_IPv4_1);
 
     try {
       membershipKey.unblock(null);
       fail();
     } catch (IllegalStateException expected) {
-      // Either of these exceptions are fine
+      // Either of these exceptions are fine.
     } catch (NullPointerException expected) {
-      // Either of these exception are fine
+      // Either of these exception are fine.
     }
 
     dc.close();
@@ -574,14 +593,14 @@
 
   public void test_unblock_mixedAddressTypes_IPv4() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1);
+    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface);
     try {
       membershipKey.unblock(UNICAST_IPv6_1);
       fail();
     } catch (IllegalStateException expected) {
-      // Either of these exceptions are fine
+      // Either of these exceptions are fine.
     } catch (IllegalArgumentException expected) {
-      // Either of these exceptions are fine
+      // Either of these exceptions are fine.
     }
 
     dc.close();
@@ -589,58 +608,70 @@
 
   public void test_unblock_mixedAddressTypes_IPv6() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, networkInterface1);
+    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv6, ipv6networkInterface);
     try {
       membershipKey.unblock(UNICAST_IPv4_1);
       fail();
     } catch (IllegalStateException expected) {
-      // Either of these exceptions are fine
+      // Either of these exceptions are fine.
     } catch (IllegalArgumentException expected) {
-      // Either of these exceptions are fine
+      // Either of these exceptions are fine.
     }
 
     dc.close();
   }
 
   /** Checks that block() works when the receiver is bound to the multicast group address */
-  public void test_block_filtersAsExpected_groupBind_ipv4() throws Exception {
-    InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface1);
-    test_block_filtersAsExpected(
-        ipv4LocalAddress /* senderBindAddress */,
-        GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
-        GOOD_MULTICAST_IPv4 /* groupAddress */);
+  public void test_block_filtersAsExpected_groupBind_IPv4() throws Exception {
+    for (NetworkInterface networkInterface : ipv4networkInterfaces) {
+      InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface);
+      test_block_filtersAsExpected(
+          networkInterface,
+          ipv4LocalAddress /* senderBindAddress */,
+          GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
+          GOOD_MULTICAST_IPv4 /* groupAddress */);
+    }
   }
 
   /** Checks that block() works when the receiver is bound to the multicast group address */
-  public void test_block_filtersAsExpected_groupBind_ipv6() throws Exception {
-    InetAddress ipv6LocalAddress = getLocalIpv6Address(IPV6networkInterface1);
-    test_block_filtersAsExpected(
-        ipv6LocalAddress /* senderBindAddress */,
-        GOOD_MULTICAST_IPv6 /* receiverBindAddress */,
-        GOOD_MULTICAST_IPv6 /* groupAddress */);
+  public void test_block_filtersAsExpected_groupBind_IPv6() throws Exception {
+    for (NetworkInterface networkInterface : ipv6networkInterfaces) {
+      InetAddress ipv6LocalAddress = getLocalIpv6Address(networkInterface);
+      test_block_filtersAsExpected(
+          networkInterface,
+          ipv6LocalAddress /* senderBindAddress */,
+          GOOD_MULTICAST_IPv6 /* receiverBindAddress */,
+          GOOD_MULTICAST_IPv6 /* groupAddress */);
+    }
   }
 
   /** Checks that block() works when the receiver is bound to the "any" address */
-  public void test_block_filtersAsExpected_anyBind_ipv4() throws Exception {
-    InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface1);
-    test_block_filtersAsExpected(
-        ipv4LocalAddress /* senderBindAddress */,
-        WILDCARD_IPv4 /* receiverBindAddress */,
-        GOOD_MULTICAST_IPv4 /* groupAddress */);
+  public void test_block_filtersAsExpected_anyBind_IPv4() throws Exception {
+    for (NetworkInterface networkInterface : ipv4networkInterfaces) {
+      InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface);
+      test_block_filtersAsExpected(
+          networkInterface,
+          ipv4LocalAddress /* senderBindAddress */,
+          WILDCARD_IPv4 /* receiverBindAddress */,
+          GOOD_MULTICAST_IPv4 /* groupAddress */);
+    }
   }
 
   /** Checks that block() works when the receiver is bound to the "any" address */
-  public void test_block_filtersAsExpected_anyBind_ipv6() throws Exception {
-    InetAddress ipv6LocalAddress = getLocalIpv6Address(IPV6networkInterface1);
-    test_block_filtersAsExpected(
-        ipv6LocalAddress /* senderBindAddress */,
-        WILDCARD_IPv6 /* receiverBindAddress */,
-        GOOD_MULTICAST_IPv6 /* groupAddress */);
+  public void test_block_filtersAsExpected_anyBind_IPv6() throws Exception {
+    for (NetworkInterface networkInterface : ipv6networkInterfaces) {
+      InetAddress ipv6LocalAddress = getLocalIpv6Address(networkInterface);
+      test_block_filtersAsExpected(
+          networkInterface,
+          ipv6LocalAddress /* senderBindAddress */,
+          WILDCARD_IPv6 /* receiverBindAddress */,
+          GOOD_MULTICAST_IPv6 /* groupAddress */);
+    }
   }
 
   private void test_block_filtersAsExpected(
-      InetAddress senderBindAddress, InetAddress receiverBindAddress, InetAddress groupAddress)
-      throws Exception {
+      NetworkInterface networkInterface, InetAddress senderBindAddress,
+      InetAddress receiverBindAddress, InetAddress groupAddress) throws Exception {
 
     DatagramChannel sendingChannel = DatagramChannel.open();
     // In order to block a sender the sender's address must be known. The sendingChannel is
@@ -657,7 +688,7 @@
     InetSocketAddress groupSocketAddress =
         new InetSocketAddress(groupAddress, localReceivingAddress.getPort());
     MembershipKey membershipKey =
-        receivingChannel.join(groupSocketAddress.getAddress(), networkInterface1);
+        receivingChannel.join(groupSocketAddress.getAddress(), networkInterface);
 
     ByteBuffer receiveBuffer = ByteBuffer.allocate(10);
 
@@ -665,10 +696,10 @@
     String msg1 = "Hello1";
     sendMessage(sendingChannel, msg1, groupSocketAddress);
     InetSocketAddress sourceAddress1 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
-    assertEquals(sourceAddress1, sendingAddress);
+    assertEquals(sendingAddress, sourceAddress1);
     assertEquals(msg1, new String(receiveBuffer.array(), 0, receiveBuffer.position()));
 
-    // Now block the sender
+    // Now block the sender.
     membershipKey.block(sendingAddress.getAddress());
 
     // Send a message. It should be filtered.
@@ -678,7 +709,7 @@
     InetSocketAddress sourceAddress2 = (InetSocketAddress) receivingChannel.receive(receiveBuffer);
     assertNull(sourceAddress2);
 
-    // Now unblock the sender
+    // Now unblock the sender.
     membershipKey.unblock(sendingAddress.getAddress());
 
     // Send a message. It should be received.
@@ -696,7 +727,7 @@
   public void test_joinSourceSpecific_nullGroupAddress() throws Exception {
     DatagramChannel dc = createReceiverChannel();
     try {
-      dc.join(null, networkInterface1, UNICAST_IPv4_1);
+      dc.join(null, ipv4networkInterface, UNICAST_IPv4_1);
       fail();
     } catch (NullPointerException expected) {
     }
@@ -707,7 +738,7 @@
     DatagramChannel dc = createReceiverChannel();
     dc.close();
     try {
-      dc.join(GOOD_MULTICAST_IPv4, networkInterface1, UNICAST_IPv4_1);
+      dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface, UNICAST_IPv4_1);
       fail();
     } catch (ClosedChannelException expected) {
     }
@@ -726,7 +757,7 @@
   public void test_joinSourceSpecific_nonMulticastGroupAddress_IPv4() throws Exception {
     DatagramChannel dc = createReceiverChannel();
     try {
-      dc.join(UNICAST_IPv4_1, networkInterface1, UNICAST_IPv4_1);
+      dc.join(UNICAST_IPv4_1, ipv4networkInterface, UNICAST_IPv4_1);
       fail();
     } catch (IllegalArgumentException expected) {
     }
@@ -736,7 +767,7 @@
   public void test_joinSourceSpecific_nonMulticastGroupAddress_IPv6() throws Exception {
     DatagramChannel dc = createReceiverChannel();
     try {
-      dc.join(UNICAST_IPv6_1, IPV6networkInterface1, UNICAST_IPv6_1);
+      dc.join(UNICAST_IPv6_1, ipv6networkInterface, UNICAST_IPv6_1);
       fail();
     } catch (IllegalArgumentException expected) {
     }
@@ -746,7 +777,7 @@
   public void test_joinSourceSpecific_nullSourceAddress_IPv4() throws Exception {
     DatagramChannel dc = createReceiverChannel();
     try {
-      dc.join(GOOD_MULTICAST_IPv4, networkInterface1, null);
+      dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface, null);
       fail();
     } catch (NullPointerException expected) {
     }
@@ -756,7 +787,7 @@
   public void test_joinSourceSpecific_nullSourceAddress_IPv6() throws Exception {
     DatagramChannel dc = createReceiverChannel();
     try {
-      dc.join(GOOD_MULTICAST_IPv6, networkInterface1, null);
+      dc.join(GOOD_MULTICAST_IPv6, ipv6networkInterface, null);
       fail();
     } catch (NullPointerException expected) {
     }
@@ -766,12 +797,12 @@
   public void test_joinSourceSpecific_mixedAddressTypes() throws Exception {
     DatagramChannel dc = createReceiverChannel();
     try {
-      dc.join(GOOD_MULTICAST_IPv4, networkInterface1, UNICAST_IPv6_1);
+      dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface, UNICAST_IPv6_1);
       fail();
     } catch (IllegalArgumentException expected) {
     }
     try {
-      dc.join(GOOD_MULTICAST_IPv6, networkInterface1, UNICAST_IPv4_1);
+      dc.join(GOOD_MULTICAST_IPv6, ipv6networkInterface, UNICAST_IPv4_1);
       fail();
     } catch (IllegalArgumentException expected) {
     }
@@ -781,17 +812,17 @@
   public void test_joinSourceSpecific_nonUnicastSourceAddress_IPv4() throws Exception {
     DatagramChannel dc = createReceiverChannel();
     try {
-      dc.join(GOOD_MULTICAST_IPv4, networkInterface1, BAD_MULTICAST_IPv4);
+      dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface, BAD_MULTICAST_IPv4);
       fail();
     } catch (IllegalArgumentException expected) {
     }
     dc.close();
   }
 
-  public void test_joinSourceSpecific_nonUniicastSourceAddress_IPv6() throws Exception {
+  public void test_joinSourceSpecific_nonUnicastSourceAddress_IPv6() throws Exception {
     DatagramChannel dc = createReceiverChannel();
     try {
-      dc.join(GOOD_MULTICAST_IPv6, networkInterface1, BAD_MULTICAST_IPv6);
+      dc.join(GOOD_MULTICAST_IPv6, ipv6networkInterface, BAD_MULTICAST_IPv6);
       fail();
     } catch (IllegalArgumentException expected) {
     }
@@ -803,7 +834,7 @@
     for (byte i = 1; i <= 20; i++) {
       InetAddress sourceAddress = Inet4Address.getByAddress(new byte[] { 10, 0, 0, i});
       try {
-        dc.join(GOOD_MULTICAST_IPv4, networkInterface1, sourceAddress);
+        dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface, sourceAddress);
       } catch (SocketException e) {
         // There is a limit, that's ok according to the RI docs. For this test a lower bound of 10
         // is used, which appears to be the default linux limit. See /proc/sys/net/ipv4/igmp_max_msf
@@ -819,72 +850,72 @@
    * Checks that a source-specific join() works when the receiver is bound to the multicast group
    * address
    */
-  public void test_joinSourceSpecific_null() throws Exception {
-    InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface1);
-    test_joinSourceSpecific(
-        ipv4LocalAddress /* senderBindAddress */,
-        GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
-        GOOD_MULTICAST_IPv4 /* groupAddress */,
-        UNICAST_IPv4_1 /* badSenderAddress */);
+  public void test_joinSourceSpecific_groupBind_IPv4() throws Exception {
+    for (NetworkInterface networkInterface : ipv4networkInterfaces) {
+      InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface);
+      test_joinSourceSpecific(
+          networkInterface,
+          ipv4LocalAddress /* senderBindAddress */,
+          GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
+          GOOD_MULTICAST_IPv4 /* groupAddress */,
+          UNICAST_IPv4_1 /* badSenderAddress */);
+    }
   }
 
   /**
    * Checks that a source-specific join() works when the receiver is bound to the multicast group
    * address
    */
-  public void test_joinSourceSpecific_groupBind_ipv4() throws Exception {
-    InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface1);
-    test_joinSourceSpecific(
-        ipv4LocalAddress /* senderBindAddress */,
-        GOOD_MULTICAST_IPv4 /* receiverBindAddress */,
-        GOOD_MULTICAST_IPv4 /* groupAddress */,
-        UNICAST_IPv4_1 /* badSenderAddress */);
-  }
-
-  /**
-   * Checks that a source-specific join() works when the receiver is bound to the multicast group
-   * address
-   */
-  public void test_joinSourceSpecific_groupBind_ipv6() throws Exception {
-    InetAddress ipv6LocalAddress = getLocalIpv6Address(IPV6networkInterface1);
-    test_joinSourceSpecific(
-        ipv6LocalAddress /* senderBindAddress */,
-        GOOD_MULTICAST_IPv6 /* receiverBindAddress */,
-        GOOD_MULTICAST_IPv6 /* groupAddress */,
-        UNICAST_IPv6_1 /* badSenderAddress */);
+  public void test_joinSourceSpecific_groupBind_IPv6() throws Exception {
+    for (NetworkInterface networkInterface : ipv6networkInterfaces) {
+      InetAddress ipv6LocalAddress = getLocalIpv6Address(networkInterface);
+      test_joinSourceSpecific(
+          networkInterface,
+          ipv6LocalAddress /* senderBindAddress */,
+          GOOD_MULTICAST_IPv6 /* receiverBindAddress */,
+          GOOD_MULTICAST_IPv6 /* groupAddress */,
+          UNICAST_IPv6_1 /* badSenderAddress */);
+    }
   }
 
   /** Checks that a source-specific join() works when the receiver is bound to the "any" address */
-  public void test_joinSourceSpecific_anyBind_ipv4() throws Exception {
-    InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface1);
-    test_joinSourceSpecific(
-        ipv4LocalAddress /* senderBindAddress */,
-        WILDCARD_IPv4 /* receiverBindAddress */,
-        GOOD_MULTICAST_IPv4 /* groupAddress */,
-        UNICAST_IPv4_1 /* badSenderAddress */);
+  public void test_joinSourceSpecific_anyBind_IPv4() throws Exception {
+    for (NetworkInterface networkInterface : ipv4networkInterfaces) {
+      InetAddress ipv4LocalAddress = getLocalIpv4Address(networkInterface);
+      test_joinSourceSpecific(
+          networkInterface,
+          ipv4LocalAddress /* senderBindAddress */,
+          WILDCARD_IPv4 /* receiverBindAddress */,
+          GOOD_MULTICAST_IPv4 /* groupAddress */,
+          UNICAST_IPv4_1 /* badSenderAddress */);
+    }
   }
 
   /** Checks that a source-specific join() works when the receiver is bound to the "any" address */
-  public void test_joinSourceSpecific_anyBind_ipv6() throws Exception {
-    InetAddress ipv6LocalAddress = getLocalIpv6Address(IPV6networkInterface1);
-    test_joinSourceSpecific(
-        ipv6LocalAddress /* senderBindAddress */,
-        WILDCARD_IPv6 /* receiverBindAddress */,
-        GOOD_MULTICAST_IPv6 /* groupAddress */,
-        UNICAST_IPv6_1 /* badSenderAddress */);
+  public void test_joinSourceSpecific_anyBind_IPv6() throws Exception {
+    for (NetworkInterface networkInterface : ipv6networkInterfaces) {
+      InetAddress ipv6LocalAddress = getLocalIpv6Address(networkInterface);
+      test_joinSourceSpecific(
+          networkInterface,
+          ipv6LocalAddress /* senderBindAddress */,
+          WILDCARD_IPv6 /* receiverBindAddress */,
+          GOOD_MULTICAST_IPv6 /* groupAddress */,
+          UNICAST_IPv6_1 /* badSenderAddress */);
+    }
   }
 
   /**
-   * Checks that the source-specific membership is correctly source-filtering.
-   * 
+   * Checks that the source-specific membership is correctly source-filtered.
+   *
+   * @param networkInterface the network interface to use when joining
    * @param senderBindAddress the address to bind the sender socket to
    * @param receiverBindAddress the address to bind the receiver socket to
    * @param groupAddress the group address to join
    * @param badSenderAddress a unicast address to join to perform a negative test
    */
   private void test_joinSourceSpecific(
-      InetAddress senderBindAddress, InetAddress receiverBindAddress, InetAddress groupAddress,
-      InetAddress badSenderAddress)
+      NetworkInterface networkInterface, InetAddress senderBindAddress,
+      InetAddress receiverBindAddress, InetAddress groupAddress, InetAddress badSenderAddress)
       throws Exception {
     DatagramChannel sendingChannel = DatagramChannel.open();
     // In order to be source-specific the sender's address must be known. The sendingChannel is
@@ -893,16 +924,16 @@
     InetSocketAddress sendingAddress = (InetSocketAddress) sendingChannel.getLocalAddress();
 
     DatagramChannel receivingChannel = DatagramChannel.open();
+    configureChannelForReceiving(receivingChannel);
     receivingChannel.bind(
         new InetSocketAddress(receiverBindAddress, 0) /* local port left to the OS to determine */);
-    configureChannelForReceiving(receivingChannel);
 
     InetSocketAddress localReceivingAddress =
         (InetSocketAddress) receivingChannel.getLocalAddress();
     InetSocketAddress groupSocketAddress =
         new InetSocketAddress(groupAddress, localReceivingAddress.getPort());
     MembershipKey membershipKey1 = receivingChannel
-        .join(groupSocketAddress.getAddress(), networkInterface1, senderBindAddress);
+        .join(groupSocketAddress.getAddress(), networkInterface, senderBindAddress);
 
     ByteBuffer receiveBuffer = ByteBuffer.allocate(10);
 
@@ -915,7 +946,7 @@
 
     membershipKey1.drop();
 
-    receivingChannel.join(groupSocketAddress.getAddress(), networkInterface1, badSenderAddress);
+    receivingChannel.join(groupSocketAddress.getAddress(), networkInterface, badSenderAddress);
 
     // Send a message. It should not be received.
     String msg2 = "Hello2";
@@ -928,50 +959,66 @@
   }
 
   public void test_dropSourceSpecific_twice_IPv4() throws Exception {
-    test_dropSourceSpecific_twice(
-        GOOD_MULTICAST_IPv4 /* groupAddress */, UNICAST_IPv4_1 /* sourceAddress */);
+    for (NetworkInterface networkInterface : ipv4networkInterfaces) {
+      test_dropSourceSpecific_twice(
+          networkInterface,
+          GOOD_MULTICAST_IPv4 /* groupAddress */,
+          UNICAST_IPv4_1 /* sourceAddress */);
+    }
   }
 
   public void test_dropSourceSpecific_twice_IPv6() throws Exception {
-    test_dropSourceSpecific_twice(
-        GOOD_MULTICAST_IPv6 /* groupAddress */, UNICAST_IPv6_1 /* sourceAddress */);
+    for (NetworkInterface networkInterface : ipv6networkInterfaces) {
+      test_dropSourceSpecific_twice(
+          networkInterface,
+          GOOD_MULTICAST_IPv6 /* groupAddress */,
+          UNICAST_IPv6_1 /* sourceAddress */);
+    }
   }
 
-  private void test_dropSourceSpecific_twice(InetAddress groupAddress, InetAddress sourceAddress)
+  private void test_dropSourceSpecific_twice(
+      NetworkInterface networkInterface, InetAddress groupAddress, InetAddress sourceAddress)
       throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(groupAddress, networkInterface1, sourceAddress);
+    MembershipKey membershipKey = dc.join(groupAddress, networkInterface, sourceAddress);
 
     assertTrue(membershipKey.isValid());
     membershipKey.drop();
     assertFalse(membershipKey.isValid());
 
-    // Try to leave a group we are no longer a member of - should do nothing.
+    // Try to leave a group we are no longer a member of. It should do nothing.
     membershipKey.drop();
 
     dc.close();
   }
 
   public void test_dropSourceSpecific_sourceKeysAreIndependent_IPv4() throws Exception {
-    test_dropSourceSpecific_sourceKeysAreIndependent(
-        GOOD_MULTICAST_IPv4 /* groupAddress */,
-        UNICAST_IPv4_1 /* sourceAddress1 */,
-        UNICAST_IPv4_2 /* sourceAddress2 */);
+    for (NetworkInterface networkInterface : ipv4networkInterfaces) {
+      test_dropSourceSpecific_sourceKeysAreIndependent(
+          networkInterface,
+          GOOD_MULTICAST_IPv4 /* groupAddress */,
+          UNICAST_IPv4_1 /* sourceAddress1 */,
+          UNICAST_IPv4_2 /* sourceAddress2 */);
+    }
   }
 
   public void test_dropSourceSpecific_sourceKeysAreIndependent_IPv6() throws Exception {
-    test_dropSourceSpecific_sourceKeysAreIndependent(
-        GOOD_MULTICAST_IPv6 /* groupAddress */,
-        UNICAST_IPv6_1 /* sourceAddress1 */,
-        UNICAST_IPv6_2 /* sourceAddress2 */);
+    for (NetworkInterface networkInterface : ipv6networkInterfaces) {
+      test_dropSourceSpecific_sourceKeysAreIndependent(
+          networkInterface,
+          GOOD_MULTICAST_IPv6 /* groupAddress */,
+          UNICAST_IPv6_1 /* sourceAddress1 */,
+          UNICAST_IPv6_2 /* sourceAddress2 */);
+    }
   }
 
   private void test_dropSourceSpecific_sourceKeysAreIndependent(
-      InetAddress groupAddress, InetAddress sourceAddress1, InetAddress sourceAddress2)
+      NetworkInterface networkInterface, InetAddress groupAddress, InetAddress sourceAddress1,
+      InetAddress sourceAddress2)
       throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey1 = dc.join(groupAddress, networkInterface1, sourceAddress1);
-    MembershipKey membershipKey2 = dc.join(groupAddress, networkInterface1, sourceAddress2);
+    MembershipKey membershipKey1 = dc.join(groupAddress, networkInterface, sourceAddress1);
+    MembershipKey membershipKey2 = dc.join(groupAddress, networkInterface, sourceAddress2);
     assertFalse(membershipKey1.equals(membershipKey2));
     assertTrue(membershipKey1.isValid());
     assertTrue(membershipKey2.isValid());
@@ -986,7 +1033,8 @@
 
   public void test_drop_keyBehaviorAfterDrop() throws Exception {
     DatagramChannel dc = createReceiverChannel();
-    MembershipKey membershipKey = dc.join(GOOD_MULTICAST_IPv4, networkInterface1, UNICAST_IPv4_1);
+    MembershipKey membershipKey =
+        dc.join(GOOD_MULTICAST_IPv4, ipv4networkInterface, UNICAST_IPv4_1);
     membershipKey.drop();
     assertFalse(membershipKey.isValid());
 
@@ -1003,18 +1051,26 @@
     assertSame(dc, membershipKey.channel());
     assertSame(GOOD_MULTICAST_IPv4, membershipKey.group());
     assertSame(UNICAST_IPv4_1, membershipKey.sourceAddress());
-    assertSame(networkInterface1, membershipKey.networkInterface());
+    assertSame(ipv4networkInterface, membershipKey.networkInterface());
+  }
+
+  private static DatagramChannel createReceiverChannel() throws Exception {
+    DatagramChannel dc = DatagramChannel.open();
+    configureChannelForReceiving(dc);
+    dc.bind(null /* leave the OS to determine the port, and use the wildcard address */);
+    return dc;
   }
 
   private static void configureChannelForReceiving(DatagramChannel receivingChannel)
       throws Exception {
 
     // NOTE: At the time of writing setSoTimeout() has no effect in the RI, making these tests hang
-    // if the channel is in blocking mode. configureBlocking(false) is used instead and rely on the
-    // network to the local host being instantaneous.
-    // receivingChannel.socket().setSoTimeout(200);
-    // receivingChannel.configureBlocking(true);
-    receivingChannel.configureBlocking(false);
+    // if the channel is in blocking mode.
+    receivingChannel.socket().setSoTimeout(200);
+    receivingChannel.configureBlocking(true);
+    // configureBlocking(false) can be used instead in the RI and we rely on the network to the
+    // local host being instantaneous.
+    // receivingChannel.configureBlocking(false);
   }
 
   private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException {
@@ -1025,22 +1081,13 @@
         && iface.getInetAddresses().hasMoreElements();
   }
 
-  private static void sendMulticastMessage(InetAddress group, int port, String msg)
-      throws IOException {
-    sendMulticastMessage(group, port, msg, null /* networkInterface */);
-  }
-
-  private static void sendMulticastMessage(
-      InetAddress group, int port, String msg, NetworkInterface sendingInterface)
+  private static void sendMessage(
+      InetAddress targetGroup, int targetPort, String msg, NetworkInterface sendingInterface)
       throws IOException {
     // Any datagram socket can send to a group. It does not need to have joined the group.
     DatagramChannel dc = DatagramChannel.open();
-    if (sendingInterface != null) {
-      // For some reason, if set, this must be set to a real (non-loopback) device for an IPv6
-      // group, but can be loopback for an IPv4 group.
-      dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, sendingInterface);
-    }
-    sendMessage(dc, msg, new InetSocketAddress(group, port));
+    dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, sendingInterface);
+    sendMessage(dc, msg, new InetSocketAddress(targetGroup, targetPort));
     dc.close();
   }
 
diff --git a/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java b/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java
index d0b46ed..09a18e2 100644
--- a/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java
+++ b/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java
@@ -53,59 +53,116 @@
 
 public class KeyPairGeneratorTest extends TestCase {
 
-    public void test_getInstance() throws Exception {
+    public void test_providerCount() {
         Provider[] providers = Security.getProviders();
-        for (Provider provider : providers) {
-            Set<Provider.Service> services = provider.getServices();
-            for (Provider.Service service : services) {
-                String type = service.getType();
-                if (!type.equals("KeyPairGenerator")) {
-                    continue;
+        // We expect there to be at least one provider.
+        assertTrue(providers.length > 0);
+        // If this fails remember to add _provider methods below. This test is sharded because it
+        // takes a long time to execute.
+        assertTrue(providers.length < 10);
+    }
+
+    public void test_getInstance_provider0() throws Exception {
+        test_getInstance(0);
+    }
+
+    public void test_getInstance_provider1() throws Exception {
+        test_getInstance(1);
+    }
+
+    public void test_getInstance_provider2() throws Exception {
+        test_getInstance(2);
+    }
+
+    public void test_getInstance_provider3() throws Exception {
+        test_getInstance(3);
+    }
+
+    public void test_getInstance_provider4() throws Exception {
+        test_getInstance(4);
+    }
+
+    public void test_getInstance_provider5() throws Exception {
+        test_getInstance(5);
+    }
+
+    public void test_getInstance_provider6() throws Exception {
+        test_getInstance(6);
+    }
+
+    public void test_getInstance_provider7() throws Exception {
+        test_getInstance(7);
+    }
+
+    public void test_getInstance_provider8() throws Exception {
+        test_getInstance(8);
+    }
+
+    public void test_getInstance_provider9() throws Exception {
+        test_getInstance(9);
+    }
+
+    private void test_getInstance(int providerIndex) throws Exception {
+        Provider[] providers = Security.getProviders();
+        if (providerIndex >= providers.length) {
+            // Providers can be added by vendors and other tests. We do not
+            // specify a fixed number and silenty pass if the provider at the
+            // specified index does not exist.
+            return;
+        }
+        Provider provider = providers[providerIndex];
+        Set<Provider.Service> services = provider.getServices();
+        for (Provider.Service service : services) {
+            String type = service.getType();
+            if (!type.equals("KeyPairGenerator")) {
+                continue;
+            }
+            String algorithm = service.getAlgorithm();
+
+            // AndroidKeyStore is tested in CTS.
+            if ("AndroidKeyStore".equals(provider.getName())) {
+                continue;
+            }
+
+            AlgorithmParameterSpec params = null;
+
+            // TODO: detect if we're running in vogar and run the full test
+            if ("DH".equals(algorithm)) {
+                // Disabled because this takes too long on devices.
+                // TODO: Re-enable DH test. http://b/5513723.
+                // params = getDHParams();
+                continue;
+            }
+
+            try {
+                // KeyPairGenerator.getInstance(String)
+                KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(algorithm);
+                assertEquals(algorithm, kpg1.getAlgorithm());
+                if (params != null) {
+                    kpg1.initialize(params);
                 }
-                String algorithm = service.getAlgorithm();
+                test_KeyPairGenerator(kpg1);
 
-                // AndroidKeyStore is tested in CTS.
-                if ("AndroidKeyStore".equals(provider.getName())) {
-                    continue;
+                // KeyPairGenerator.getInstance(String, Provider)
+                KeyPairGenerator kpg2 = KeyPairGenerator.getInstance(algorithm, provider);
+                assertEquals(algorithm, kpg2.getAlgorithm());
+                assertEquals(provider, kpg2.getProvider());
+                if (params != null) {
+                    kpg2.initialize(params);
                 }
+                test_KeyPairGenerator(kpg2);
 
-                AlgorithmParameterSpec params = null;
-
-                // TODO: detect if we're running in vogar and run the full test
-                if ("DH".equals(algorithm)) {
-                    params = getDHParams();
+                // KeyPairGenerator.getInstance(String, String)
+                KeyPairGenerator kpg3 = KeyPairGenerator.getInstance(algorithm,
+                                                                    provider.getName());
+                assertEquals(algorithm, kpg3.getAlgorithm());
+                assertEquals(provider, kpg3.getProvider());
+                if (params != null) {
+                    kpg3.initialize(params);
                 }
-
-                try {
-                    // KeyPairGenerator.getInstance(String)
-                    KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(algorithm);
-                    assertEquals(algorithm, kpg1.getAlgorithm());
-                    if (params != null) {
-                        kpg1.initialize(params);
-                    }
-                    test_KeyPairGenerator(kpg1);
-
-                    // KeyPairGenerator.getInstance(String, Provider)
-                    KeyPairGenerator kpg2 = KeyPairGenerator.getInstance(algorithm, provider);
-                    assertEquals(algorithm, kpg2.getAlgorithm());
-                    assertEquals(provider, kpg2.getProvider());
-                    if (params != null) {
-                        kpg2.initialize(params);
-                    }
-                    test_KeyPairGenerator(kpg2);
-
-                    // KeyPairGenerator.getInstance(String, String)
-                    KeyPairGenerator kpg3 = KeyPairGenerator.getInstance(algorithm,
-                                                                        provider.getName());
-                    assertEquals(algorithm, kpg3.getAlgorithm());
-                    assertEquals(provider, kpg3.getProvider());
-                    if (params != null) {
-                        kpg3.initialize(params);
-                    }
-                    test_KeyPairGenerator(kpg3);
-                } catch (Exception e) {
-                    throw new Exception("Problem testing KeyPairGenerator." + algorithm, e);
-                }
+                test_KeyPairGenerator(kpg3);
+            } catch (Exception e) {
+                throw new Exception("Problem testing KeyPairGenerator." + algorithm, e);
             }
         }
     }
@@ -341,8 +398,6 @@
     public void testDSAGeneratorWithParams() throws Exception {
         final DSAParameterSpec dsaSpec = new DSAParameterSpec(DSA_P, DSA_Q, DSA_G);
 
-        boolean failure = false;
-
         final Provider[] providers = Security.getProviders();
         for (final Provider p : providers) {
             Service s = p.getService("KeyPairGenerator", "DSA");
diff --git a/luni/src/test/java/libcore/java/sql/ConnectionTest.java b/luni/src/test/java/libcore/java/sql/ConnectionTest.java
new file mode 100644
index 0000000..02046fc
--- /dev/null
+++ b/luni/src/test/java/libcore/java/sql/ConnectionTest.java
@@ -0,0 +1,69 @@
+package libcore.java.sql;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+
+public class ConnectionTest extends TestCase {
+
+    private File dbFile = null;
+    private String connectionURL = null;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        // Trigger the static initializer that will cause the driver to register itself with
+        // DriverManager.
+        Class.forName("SQLite.JDBCDriver");
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        if (dbFile != null) {
+            dbFile.delete();
+        }
+    }
+
+    public void testDriverManager_getConnection() throws Exception {
+        Connection c = DriverManager.getConnection(getConnectionURL());
+        assertFalse(c.isClosed());
+        c.close();
+        assertTrue(c.isClosed());
+    }
+
+    public void testConnect() throws Exception {
+        Driver driver = DriverManager.getDriver(getConnectionURL());
+        assertNotNull(driver);
+        Connection c = driver.connect(getConnectionURL(), null);
+        assertFalse(c.isClosed());
+        c.close();
+        assertTrue(c.isClosed());
+    }
+
+    private String getConnectionURL() {
+        if (connectionURL == null) {
+            String tmp = System.getProperty("java.io.tmpdir");
+            File tmpDir = new File(tmp);
+            if (tmpDir.isDirectory()) {
+                try {
+                    dbFile = File.createTempFile("OldJDBCDriverTest", ".db", tmpDir);
+                } catch (IOException e) {
+                    System.err.println("error creating temporary DB file.");
+                }
+                dbFile.deleteOnExit();
+            } else {
+                System.err.println("java.io.tmpdir does not exist");
+            }
+
+            connectionURL = "jdbc:sqlite:/" + dbFile.getPath();
+        }
+
+        return connectionURL;
+    }
+}
diff --git a/luni/src/test/java/libcore/java/sql/DriverTest.java b/luni/src/test/java/libcore/java/sql/DriverTest.java
new file mode 100644
index 0000000..59d13bd
--- /dev/null
+++ b/luni/src/test/java/libcore/java/sql/DriverTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.sql;
+
+import junit.framework.TestCase;
+
+import SQLite.JDBCDriver;
+
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+
+public final class DriverTest extends TestCase {
+
+    public static final String SQLITE_JDBC_URL = "jdbc:sqlite:/only_used_at_connect_time";
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        // Trigger the static initializer that will cause the driver to register itself with
+        // DriverManager.
+        Class.forName("SQLite.JDBCDriver");
+    }
+
+    public void testDriverImplementation() throws Exception {
+        Driver driver = getDriver();
+        assertTrue(driver instanceof JDBCDriver);
+    }
+
+    public void testAcceptsURL() throws Exception {
+        Driver driver = getDriver();
+        assertTrue(driver.acceptsURL(SQLITE_JDBC_URL));
+    }
+
+    public void testGetMajorVersion() throws Exception {
+        assertTrue(getDriver().getMajorVersion() > 0);
+    }
+
+    public void testGetMinorVersion() throws Exception {
+        assertTrue(getDriver().getMinorVersion() > 0);
+    }
+
+    public void testGetPropertyInfo() throws Exception {
+        Driver driver = getDriver();
+        DriverPropertyInfo[] info = driver.getPropertyInfo(SQLITE_JDBC_URL, null);
+        assertNotNull(info);
+        assertTrue(info.length > 0);
+    }
+
+    public void testJdbcCompliant() throws Exception {
+        // The SQLite JDBC driver used by these tests is not actually JDBC compliant.
+        assertFalse(getDriver().jdbcCompliant());
+    }
+
+    private Driver getDriver() throws SQLException {
+        Driver driver = DriverManager.getDriver(SQLITE_JDBC_URL);
+        assertNotNull(driver);
+        return driver;
+    }
+}
diff --git a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
index c58f83a..0eae20a 100644
--- a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
@@ -124,21 +124,21 @@
         df.setMaximumFractionDigits(2);
         df.setMultiplier(2);
         assertEquals(df.format(BigDecimal.valueOf(0.16)),
-        df.format(BigDecimal.valueOf(0.16).doubleValue()));
+                df.format(BigDecimal.valueOf(0.16).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(0.0293)),
-        df.format(BigDecimal.valueOf(0.0293).doubleValue()));
+                df.format(BigDecimal.valueOf(0.0293).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(0.006)),
-        df.format(BigDecimal.valueOf(0.006).doubleValue()));
+                df.format(BigDecimal.valueOf(0.006).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(0.00283)),
-        df.format(BigDecimal.valueOf(0.00283).doubleValue()));
+                df.format(BigDecimal.valueOf(0.00283).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(1.60)),
         df.format(BigDecimal.valueOf(1.60).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(15)),
-        df.format(BigDecimal.valueOf(15).doubleValue()));
+                df.format(BigDecimal.valueOf(15).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(170)),
-        df.format(BigDecimal.valueOf(170).doubleValue()));
+                df.format(BigDecimal.valueOf(170).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(234.56)),
-        df.format(BigDecimal.valueOf(234.56).doubleValue()));
+                df.format(BigDecimal.valueOf(234.56).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(0)),
         df.format(BigDecimal.valueOf(0).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(-1)),
@@ -146,11 +146,11 @@
         assertEquals(df.format(BigDecimal.valueOf(-10000)),
         df.format(BigDecimal.valueOf(-10000).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(-0.001)),
-        df.format(BigDecimal.valueOf(-0.001).doubleValue()));
+                df.format(BigDecimal.valueOf(-0.001).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(1234567890.1234567)),
-        df.format(BigDecimal.valueOf(1234567890.1234567).doubleValue()));
+                df.format(BigDecimal.valueOf(1234567890.1234567).doubleValue()));
         assertEquals(df.format(BigDecimal.valueOf(1.234567E100)),
-        df.format(BigDecimal.valueOf(1.234567E100).doubleValue()));
+                df.format(BigDecimal.valueOf(1.234567E100).doubleValue()));
     }
 
     private void assertBigDecimalWithFraction(BigDecimal bd, String expectedResult, int fraction) {
@@ -260,4 +260,62 @@
       } catch (NullPointerException expected) {
       }
     }
+
+    // Confirm the fraction digits do not change when the currency is changed.
+    public void testBug71369() {
+        final String nonBreakingSpace = "\u00A0";
+
+        NumberFormat numberFormat = NumberFormat.getCurrencyInstance(Locale.GERMAN);
+        numberFormat.setCurrency(Currency.getInstance("USD"));
+
+        assertEquals("2,01" + nonBreakingSpace + "$", numberFormat.format(2.01));
+
+        numberFormat.setMinimumFractionDigits(0);
+        numberFormat.setMaximumFractionDigits(0);
+
+        String expected = "2" + nonBreakingSpace + "$";
+        assertEquals(expected, numberFormat.format(2.01));
+
+        // Changing the currency must not reset the digits.
+        numberFormat.setCurrency(Currency.getInstance("EUR"));
+        numberFormat.setCurrency(Currency.getInstance("USD"));
+
+        assertEquals(expected, numberFormat.format(2.01));
+    }
+
+    // Confirm the currency symbol used by a format is determined by the locale of the format
+    // not the current default Locale.
+    public void testSetCurrency_symbolOrigin() {
+        Currency currency = Currency.getInstance("CNY");
+        Locale locale1 = Locale.CHINA;
+        Locale locale2 = Locale.US;
+        String locale1Symbol = currency.getSymbol(locale1);
+        String locale2Symbol = currency.getSymbol(locale2);
+        // This test only works if we can tell where the symbol came from, which requires they are
+        // different across the two locales chosen.
+        assertFalse(locale1Symbol.equals(locale2Symbol));
+
+        Locale originalLocale = Locale.getDefault();
+        try {
+            Locale.setDefault(locale1);
+            String amountDefaultLocale1 =
+                    formatArbitraryCurrencyAmountInLocale(currency, locale2);
+
+            Locale.setDefault(locale2);
+            String amountDefaultLocale2 =
+                    formatArbitraryCurrencyAmountInLocale(currency, locale2);
+
+            // This used to fail because Currency.getSymbol() was used without providing the
+            // format's locale.
+            assertEquals(amountDefaultLocale1, amountDefaultLocale2);
+        } finally {
+            Locale.setDefault(originalLocale);
+        }
+    }
+
+    private String formatArbitraryCurrencyAmountInLocale(Currency currency, Locale locale) {
+        NumberFormat localeCurrencyFormat = NumberFormat.getCurrencyInstance(locale);
+        localeCurrencyFormat.setCurrency(currency);
+        return localeCurrencyFormat.format(1000);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/LocaleInternalsTest.java b/luni/src/test/java/libcore/java/util/LocaleInternalsTest.java
new file mode 100644
index 0000000..5a8a6cf
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/LocaleInternalsTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package libcore.java.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import junit.framework.TestCase;
+import libcore.icu.ICU;
+
+public class LocaleInternalsTest extends TestCase {
+
+    public void test_serializeExtensions() {
+        Map<Character, String> extensions = new TreeMap<Character, String>();
+
+        extensions.put('x', "fooo-baar-baaz");
+        assertEquals("x-fooo-baar-baaz", Locale.serializeExtensions(extensions));
+
+        extensions.put('y', "gaaa-caar-caaz");
+        // Must show up in lexical order.
+        assertEquals("x-fooo-baar-baaz-y-gaaa-caar-caaz",
+                Locale.serializeExtensions(extensions));
+    }
+
+    public void test_parseSerializedExtensions() {
+        Map<Character, String> extensions = new HashMap<Character, String>();
+
+        Locale.parseSerializedExtensions("x-foo", extensions);
+        assertEquals("foo", extensions.get('x'));
+
+        extensions.clear();
+        Locale.parseSerializedExtensions("x-foo-y-bar-z-baz", extensions);
+        assertEquals("foo", extensions.get('x'));
+        assertEquals("bar", extensions.get('y'));
+        assertEquals("baz", extensions.get('z'));
+
+        extensions.clear();
+        Locale.parseSerializedExtensions("x-fooo-baar-baaz", extensions);
+        assertEquals("fooo-baar-baaz", extensions.get('x'));
+
+        extensions.clear();
+        Locale.parseSerializedExtensions("x-fooo-baar-baaz-y-gaaa-caar-caaz", extensions);
+        assertEquals("fooo-baar-baaz", extensions.get('x'));
+        assertEquals("gaaa-caar-caaz", extensions.get('y'));
+    }
+
+    public void test_parseUnicodeExtension() {
+        Map<String, String> keywords = new HashMap<String, String>();
+        Set<String> attributes = new HashSet<String>();
+
+        // Only attributes.
+        Locale.parseUnicodeExtension("foooo".split("-"), keywords, attributes);
+        assertTrue(attributes.contains("foooo"));
+        assertTrue(keywords.isEmpty());
+
+        attributes.clear();
+        keywords.clear();
+        Locale.parseUnicodeExtension("foooo-baa-baaabaaa".split("-"),
+                keywords, attributes);
+        assertTrue(attributes.contains("foooo"));
+        assertTrue(attributes.contains("baa"));
+        assertTrue(attributes.contains("baaabaaa"));
+        assertTrue(keywords.isEmpty());
+
+        // Only keywords
+        attributes.clear();
+        keywords.clear();
+        Locale.parseUnicodeExtension("ko-koko".split("-"), keywords, attributes);
+        assertTrue(attributes.isEmpty());
+        assertEquals("koko", keywords.get("ko"));
+
+        attributes.clear();
+        keywords.clear();
+        Locale.parseUnicodeExtension("ko-koko-kokoko".split("-"), keywords, attributes);
+        assertTrue(attributes.isEmpty());
+        assertEquals("koko-kokoko", keywords.get("ko"));
+
+        attributes.clear();
+        keywords.clear();
+        Locale.parseUnicodeExtension("ko-koko-kokoko-ba-baba-bababa".split("-"),
+                keywords, attributes);
+        assertTrue(attributes.isEmpty());
+        assertEquals("koko-kokoko", keywords.get("ko"));
+        assertEquals("baba-bababa", keywords.get("ba"));
+
+        // A mixture of attributes and keywords.
+        attributes.clear();
+        keywords.clear();
+        Locale.parseUnicodeExtension("attri1-attri2-k1-type1-type1-k2-type2".split("-"),
+                keywords, attributes);
+        assertTrue(attributes.contains("attri1"));
+        assertTrue(attributes.contains("attri2"));
+        assertEquals("type1-type1", keywords.get("k1"));
+        assertEquals("type2", keywords.get("k2"));
+    }
+
+    public void test_setDefault_setsICUDefaultLocale() {
+        Locale.setDefault(Locale.GERMANY);
+        assertEquals("de_DE", ICU.getDefaultLocale());
+
+        try {
+            Locale.setDefault(null);
+            fail();
+        } catch (NullPointerException expected) {
+            assertEquals(Locale.GERMANY, Locale.getDefault());
+        }
+
+        Locale.setDefault(new Locale("bogus", "LOCALE"));
+        assertEquals("bogus__LOCALE", ICU.getDefaultLocale());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java
index baa53e9..f3b31bb 100644
--- a/luni/src/test/java/libcore/java/util/LocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/LocaleTest.java
@@ -22,15 +22,9 @@
 import java.text.DateFormatSymbols;
 import java.text.NumberFormat;
 import java.util.Calendar;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.IllformedLocaleException;
 import java.util.Locale;
-import java.util.Map;
 import java.util.MissingResourceException;
-import java.util.Set;
-import java.util.TreeMap;
-import libcore.icu.ICU;
 
 public class LocaleTest extends junit.framework.TestCase {
     // http://b/2611311; if there's no display language/country/variant, use the raw codes.
@@ -45,9 +39,22 @@
         // and variant, but a display name made up of the raw strings.
         // Newer releases return slightly different results, but no less unreasonable.
         assertEquals("aabbcc", invalid.getDisplayLanguage());
-        assertEquals("", invalid.getDisplayCountry());
-        assertEquals("DDEEFF_GGHHII", invalid.getDisplayVariant());
-        assertEquals("aabbcc (DDEEFF,DDEEFF_GGHHII)", invalid.getDisplayName());
+        assertEquals("DDEEFF", invalid.getDisplayCountry());
+        assertEquals("GGHHII", invalid.getDisplayVariant());
+        assertEquals("aabbcc (DDEEFF,GGHHII)", invalid.getDisplayName());
+    }
+
+    public void test_getDisplayName_emptyCodes() {
+        Locale emptyLanguage = new Locale("", "DdeEFf");
+        assertEquals("", emptyLanguage.getDisplayLanguage());
+
+        Locale emptyCountry = new Locale("AaBbCc", "");
+        assertEquals("", emptyCountry.getDisplayCountry());
+
+        Locale emptyCountryAndLanguage = new Locale("", "", "Farl");
+        assertEquals("", emptyCountryAndLanguage.getDisplayLanguage());
+        assertEquals("", emptyCountryAndLanguage.getDisplayCountry());
+        assertEquals("Farl", emptyCountryAndLanguage.getDisplayVariant());
     }
 
     // http://b/2611311; if there's no display language/country/variant, use the raw codes.
@@ -59,8 +66,8 @@
 
         assertEquals("xx", unknown.getDisplayLanguage());
         assertEquals("YY", unknown.getDisplayCountry());
-        assertEquals("TRADITIONAL", unknown.getDisplayVariant());
-        assertEquals("xx (YY,TRADITIONAL)", unknown.getDisplayName());
+        assertEquals("Traditional", unknown.getDisplayVariant());
+        assertEquals("xx (YY,Traditional)", unknown.getDisplayName());
     }
 
     public void test_getDisplayName_easy() throws Exception {
@@ -179,6 +186,10 @@
         assertEquals("CAN", new Locale("", "CA").getISO3Country());
         assertEquals("CAN", new Locale("en", "CA").getISO3Country());
         assertEquals("CAN", new Locale("xx", "CA").getISO3Country());
+
+        // 3 letter country codes.
+        assertEquals("CAN", new Locale("en", "CAN").getISO3Country());
+        assertEquals("CAN", new Locale("frankenderp", "CAN").getISO3Country());
     }
 
     public void test_getISO3Language() {
@@ -198,90 +209,10 @@
         assertEquals("eng", new Locale("en", "").getISO3Language());
         assertEquals("eng", new Locale("en", "CA").getISO3Language());
         assertEquals("eng", new Locale("en", "XX").getISO3Language());
-    }
 
-    public void test_serializeExtensions() {
-        Map<Character, String> extensions = new TreeMap<Character, String>();
-
-        extensions.put('x', "fooo-baar-baaz");
-        assertEquals("x-fooo-baar-baaz", Locale.serializeExtensions(extensions));
-
-        extensions.put('y', "gaaa-caar-caaz");
-        // Must show up in lexical order.
-        assertEquals("x-fooo-baar-baaz-y-gaaa-caar-caaz",
-                Locale.serializeExtensions(extensions));
-    }
-
-    public void test_parseSerializedExtensions() {
-        Map<Character, String> extensions = new HashMap<Character, String>();
-
-        Locale.parseSerializedExtensions("x-foo", extensions);
-        assertEquals("foo", extensions.get('x'));
-
-        extensions.clear();
-        Locale.parseSerializedExtensions("x-foo-y-bar-z-baz", extensions);
-        assertEquals("foo", extensions.get('x'));
-        assertEquals("bar", extensions.get('y'));
-        assertEquals("baz", extensions.get('z'));
-
-        extensions.clear();
-        Locale.parseSerializedExtensions("x-fooo-baar-baaz", extensions);
-        assertEquals("fooo-baar-baaz", extensions.get('x'));
-
-        extensions.clear();
-        Locale.parseSerializedExtensions("x-fooo-baar-baaz-y-gaaa-caar-caaz", extensions);
-        assertEquals("fooo-baar-baaz", extensions.get('x'));
-        assertEquals("gaaa-caar-caaz", extensions.get('y'));
-    }
-
-    public void test_parseUnicodeExtension() {
-        Map<String, String> keywords = new HashMap<String, String>();
-        Set<String> attributes = new HashSet<String>();
-
-        // Only attributes.
-        Locale.parseUnicodeExtension("foooo".split("-"), keywords, attributes);
-        assertTrue(attributes.contains("foooo"));
-        assertTrue(keywords.isEmpty());
-
-        attributes.clear();
-        keywords.clear();
-        Locale.parseUnicodeExtension("foooo-baa-baaabaaa".split("-"),
-                keywords, attributes);
-        assertTrue(attributes.contains("foooo"));
-        assertTrue(attributes.contains("baa"));
-        assertTrue(attributes.contains("baaabaaa"));
-        assertTrue(keywords.isEmpty());
-
-        // Only keywords
-        attributes.clear();
-        keywords.clear();
-        Locale.parseUnicodeExtension("ko-koko".split("-"), keywords, attributes);
-        assertTrue(attributes.isEmpty());
-        assertEquals("koko", keywords.get("ko"));
-
-        attributes.clear();
-        keywords.clear();
-        Locale.parseUnicodeExtension("ko-koko-kokoko".split("-"), keywords, attributes);
-        assertTrue(attributes.isEmpty());
-        assertEquals("koko-kokoko", keywords.get("ko"));
-
-        attributes.clear();
-        keywords.clear();
-        Locale.parseUnicodeExtension("ko-koko-kokoko-ba-baba-bababa".split("-"),
-                keywords, attributes);
-        assertTrue(attributes.isEmpty());
-        assertEquals("koko-kokoko", keywords.get("ko"));
-        assertEquals("baba-bababa", keywords.get("ba"));
-
-        // A mixture of attributes and keywords.
-        attributes.clear();
-        keywords.clear();
-        Locale.parseUnicodeExtension("attri1-attri2-k1-type1-type1-k2-type2".split("-"),
-                keywords, attributes);
-        assertTrue(attributes.contains("attri1"));
-        assertTrue(attributes.contains("attri2"));
-        assertEquals("type1-type1", keywords.get("k1"));
-        assertEquals("type2", keywords.get("k2"));
+        // 3 letter language code.
+        assertEquals("eng", new Locale("eng", "USA").getISO3Language());
+        assertEquals("eng", new Locale("eng", "US").getISO3Language());
     }
 
     public void test_Builder_setLanguage() {
@@ -1105,7 +1036,7 @@
     }
 
     public void test_toString() {
-                Locale.Builder b = new Locale.Builder();
+        Locale.Builder b = new Locale.Builder();
 
         // Empty builder.
         Locale l = b.build();
@@ -1164,21 +1095,6 @@
         Locale posix = new Locale.Builder()
                 .setLanguage("en").setRegion("US").setVariant("POSIX")
                 .build();
-        assertEquals("en-US-u-va-posix", posix.toLanguageTag());
-    }
-
-    public void test_setDefault_setsICUDefaultLocale() {
-        Locale.setDefault(Locale.GERMANY);
-        assertEquals("de_DE", ICU.getDefaultLocale());
-
-        try {
-            Locale.setDefault(null);
-            fail();
-        } catch (NullPointerException expected) {
-            assertEquals(Locale.GERMANY, Locale.getDefault());
-        }
-
-        Locale.setDefault(new Locale("bogus", "LOCALE"));
-        assertEquals("bogus__LOCALE", ICU.getDefaultLocale());
+        assertEquals("en-US-POSIX", posix.toLanguageTag());
     }
 }
diff --git a/luni/src/test/java/libcore/sqlite/AbstractSqlTest.java b/luni/src/test/java/libcore/sqlite/AbstractSqlTest.java
deleted file mode 100644
index d194548..0000000
--- a/luni/src/test/java/libcore/sqlite/AbstractSqlTest.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.sqlite;
-
-import SQLite.Exception;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import junit.framework.TestCase;
-
-
-/**
- * This class provides SQL unit test, which can be used by subclasses eg. to
- * test JDBC drivers.
- */
-abstract class AbstractSqlTest extends TestCase {
-
-    /**
-     * The first connection.
-     */
-    private Connection firstConnection;
-
-    /**
-     * The second connection.
-     */
-    private Connection secondConnection;
-
-    /**
-     * The statement from the first connection.
-     */
-    private Statement firstStmt;
-
-    /**
-     * The statement from the second connection.
-     */
-    private Statement secondStmt;
-
-    /**
-     * The values of the first column "one".
-     */
-    private final String[] ones = {"hello!", "goodbye"};
-
-    /**
-     * The values of the second column "two".
-     */
-    private final short[] twos = {10, 20};
-
-    /**
-     * The updated values of the first column "one".
-     */
-    private final String[] ones_updated;
-
-    /** Creates a new instance of this class */
-    public AbstractSqlTest() {
-        super();
-        ones_updated = new String[ones.length];
-        for (int i = 0; i < ones.length; i++) {
-            ones_updated[i] = ones[i] + twos[i];
-        }
-    }
-
-    /**
-     * Sets up a unit test, by creating two statements from two connections and
-     * creating a test table.
-     *
-     * @exception SQLException if there is a problem accessing the database
-     * @throws Exception
-     * @exception Exception may be thrown by subclasses
-     */
-    @Override
-    protected void setUp() throws java.lang.Exception {
-        Class.forName(getDriverClassName()).newInstance();
-        firstConnection = DriverManager.getConnection(getConnectionURL());
-        firstConnection.setTransactionIsolation(getTransactionIsolation());
-        secondConnection = DriverManager.getConnection(getConnectionURL());
-        secondConnection.setTransactionIsolation(getTransactionIsolation());
-        firstStmt = firstConnection.createStatement();
-        firstStmt.execute("create table tbl1(one varchar(10), two smallint)");
-        secondStmt = secondConnection.createStatement();
-    }
-
-    /**
-     * Tears down a unit test, by setting the auto commit property of the first
-     * connection back to true, dropping the test table and closing the two
-     * connections.
-     */
-    @Override
-    protected void tearDown() throws SQLException {
-        firstStmt.close();
-        secondStmt.close();
-        firstConnection.setAutoCommit(true);
-        firstStmt = firstConnection.createStatement();
-        firstStmt.execute("drop table tbl1");
-        firstStmt.close();
-        firstConnection.close();
-        secondConnection.close();
-    }
-
-    /**
-     * Adds some rows to the test table and asserts that the rows can be
-     * retrieved again.
-     *
-     * @throws SQLException if there is a problem accessing the database
-     */
-    private void autoCommitInsertSelect() throws SQLException {
-        firstStmt.getConnection().setAutoCommit(true);
-        for (int i = 0; i < ones.length; i++) {
-            firstStmt.execute("insert into tbl1 values('" + ones[i] + "',"
-                    + twos[i] + ")");
-        }
-        assertAllFromTbl1(firstStmt, ones, twos);
-    }
-
-    /**
-     * Asserts that the expected values can be selected from the test table.
-     *
-     * @param stmt the statement to be used for the selection of the data
-     * @param ones the expected values of the column 'one'
-     * @param twos the expected values of the column 'two'
-     * @throws SQLException if there is a problem accessing the database
-     */
-    private void assertAllFromTbl1(Statement stmt, String[] ones, short[] twos)
-            throws SQLException {
-        ResultSet rs = stmt.executeQuery("select * from tbl1");
-        int i = 0;
-        for (; rs.next(); i++) {
-            assertTrue(i < ones.length);
-            assertEquals(ones[i], rs.getString("one"));
-            assertEquals(twos[i], rs.getShort("two"));
-        }
-        assertTrue(i == ones.length);
-    }
-
-    public void testAutoCommitInsertSelect() throws SQLException{
-        autoCommitInsertSelect();
-    }
-
-    /**
-     * Tests the following sequence after successful insertion of some test
-     * data:
-     * - update data from connection one
-     * - select data from connection two (-> should have the old values)
-     * - commit data from connection one
-     * - select data from connection two (-> should have the new values)
-     *
-     * @throws SQLException if there is a problem accessing the database
-     */
-    public void testUpdateSelectCommitSelect() throws SQLException {
-        autoCommitInsertSelect();
-        firstStmt.getConnection().setAutoCommit(false);
-        updateOnes(firstStmt, ones_updated, twos);
-        assertAllFromTbl1(secondStmt, ones, twos);
-        firstStmt.getConnection().commit();
-        assertAllFromTbl1(secondStmt, ones_updated, twos);
-    }
-
-    /**
-     * Tests the following sequence after successful insertion of some test
-     * data:
-     * - update data from connection one
-     * - select data from connection two (-> should have the old values)
-     * - rollback data from connection one
-     * - select data from connection two (-> should still have the old values)
-     *
-     * @throws SQLException if there is a problem accessing the database
-     */
-    public void testUpdateSelectRollbackSelect() throws SQLException {
-        autoCommitInsertSelect();
-        firstStmt.getConnection().setAutoCommit(false);
-        updateOnes(firstStmt, ones_updated, twos);
-        assertAllFromTbl1(secondStmt, ones, twos);
-        firstStmt.getConnection().rollback();
-        assertAllFromTbl1(secondStmt, ones, twos);
-    }
-
-    /**
-     * Updates the values in column 'one'
-     * @param stmt the statement to be used to update the data
-     * @param ones_updated the updated valus of column 'one'
-     * @param twos the reference values of column 'two'
-     * @throws SQLException if there is a problem accessing the database
-     */
-    private void updateOnes(Statement stmt, String[] ones_updated, short[] twos)
-            throws SQLException {
-        for (int i = 0; i < ones_updated.length; i++) {
-            stmt.execute("UPDATE tbl1 SET one = '" + ones_updated[i]
-                    + "' WHERE two = " + twos[i]);
-        }
-    }
-
-    protected abstract String getConnectionURL();
-
-    protected abstract String getDriverClassName();
-
-    protected abstract int getTransactionIsolation();
-
-}
diff --git a/luni/src/test/java/libcore/sqlite/OldBlobTest.java b/luni/src/test/java/libcore/sqlite/OldBlobTest.java
deleted file mode 100644
index 3289d38..0000000
--- a/luni/src/test/java/libcore/sqlite/OldBlobTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.sqlite;
-
-import SQLite.Blob;
-import SQLite.Database;
-import SQLite.Exception;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import tests.support.Support_SQL;
-
-public final class OldBlobTest extends OldSQLiteTest {
-
-    private static Blob testBlob = null;
-
-    private static Database db = null;
-
-    public void setUp() throws java.lang.Exception {
-        super.setUp();
-        testBlob = new Blob();
-
-        super.setUp();
-        Support_SQL.loadDriver();
-        db = new Database();
-        db.open(dbFile.getPath(), 0);
-
-        db.exec("create table B(id integer primary key, val blob)",null);
-        db.exec("insert into B values(1, zeroblob(128))", null);
-        db.exec("insert into B values(2, zeroblob(128))", null);
-        db.exec("insert into B values(3, zeroblob(128))", null);
-
-        // can not fill Blob with data at this point...
-        /*
-        File resources = Support_Resources.createTempFolder();
-        BufferedReader r = null;
-        try {
-            Class c = Class.forName(this.getClass().getName());
-            assertNotNull(c);
-            file = Class.forName(this.getClass().getName())
-                    .getResourceAsStream("/blob.c");
-            r = new BufferedReader(new InputStreamReader(file));
-        } catch (NullPointerException e) {
-            fail("Should not throw NullPointerException reading file"
-                    + e.getMessage());
-        }
-        OutputStream out = testBlob.getOutputStream();
-        String s = null;
-        while ((s = r.readLine()) != null) {
-            out.write(r.readLine().getBytes());
-        }
-        out.flush();
-        out.close();
-        testBlob.close();
-        */
-    }
-
-    @Override public void tearDown() throws java.lang.Exception {
-        testBlob.close();
-        super.tearDown();
-    }
-
-    /**
-     * db.open_blob is not supported.
-     */
-    public void testBlob() throws Exception, IOException {
-        byte[] b = new byte[4];
-        byte[] b128 = new byte[128];
-        for (int i = 0; i < b128.length; i++) {
-        b128[i] = (byte) i;
-        }
-        Blob blob = db.open_blob(dbFile.getPath(), "B", "val", 1, true);
-        try {
-
-        OutputStream os = blob.getOutputStream();
-        os.write(b128);
-        os.close();
-
-        InputStream is = blob.getInputStream();
-        is.skip(96);
-        assertEquals(4,is.read(b));
-        is.close();
-        } finally {
-        blob.close();
-        }
-    }
-
-    public void testGetInputStream() {
-        InputStream in = testBlob.getInputStream();
-        try {
-            in.read();
-            fail("Exception not thrown for invalid Blob.");
-        } catch (Throwable e) {
-            //ok
-        }
-    }
-
-    public void testGetOutputStream() {
-        OutputStream out = testBlob.getOutputStream();
-
-        try {
-           out.write(null);
-           fail("Write operation unsupported");
-        } catch (Throwable e) {
-            assertEquals("Write operation unsupported", e.getMessage());
-        }
-    }
-
-    public void testClose() {
-        assertNotNull(testBlob);
-
-        testBlob.close();
-        // inputStream either null or some error occurs
-        try {
-            // TODO This does look a bit weird. Revisit later.
-            assertNull(testBlob.getInputStream());
-        } catch (Throwable e) {
-            //ok
-        }
-    }
-}
diff --git a/luni/src/test/java/libcore/sqlite/OldDatabaseTest.java b/luni/src/test/java/libcore/sqlite/OldDatabaseTest.java
deleted file mode 100644
index f2cbc57..0000000
--- a/luni/src/test/java/libcore/sqlite/OldDatabaseTest.java
+++ /dev/null
@@ -1,1224 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.sqlite;
-
-import SQLite.Authorizer;
-import SQLite.Blob;
-import SQLite.BusyHandler;
-import SQLite.Callback;
-import SQLite.Constants;
-import SQLite.Database;
-import SQLite.Exception;
-import SQLite.Function;
-import SQLite.FunctionContext;
-import SQLite.ProgressHandler;
-import SQLite.Stmt;
-import SQLite.TableResult;
-import SQLite.Trace;
-import SQLite.Vm;
-import java.io.File;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URL;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.logging.Logger;
-import tests.support.DatabaseCreator;
-import tests.support.MockFunction;
-import tests.support.ThreadPool;
-
-public final class OldDatabaseTest extends OldSQLiteTest {
-
-    private static ErrorTracker tracker = null;
-
-    private Statement statement;
-
-    private Database db = null;
-
-    private static final int numThreads = 10;
-
-    private static final int numOfRecords = 30;
-
-    @Override public void setUp() throws java.lang.Exception {
-        super.setUp();
-        assertNotNull("Could not establish DB connection",conn);
-        tracker = new ErrorTracker();
-
-        statement = conn.createStatement();
-
-        // Cleanup tables if necessary
-
-        DatabaseMetaData meta = conn.getMetaData();
-        assertNotNull(meta);
-        ResultSet userTab = meta.getTables(null, null, null, null);
-        while (userTab.next()) {
-            String tableName = userTab.getString("TABLE_NAME");
-            this.statement.execute("drop table " + tableName);
-        }
-
-        // Create default test table
-        statement.execute(DatabaseCreator.CREATE_TABLE_SIMPLE1);
-        statement.close();
-
-        db = new Database();
-        db.open(dbFile.getPath(), 0);
-        db.busy_handler(null);
-    }
-
-    public void tearDown() throws java.lang.Exception {
-        try {
-            db.close();
-        } catch (Exception e) {
-            if (!(e.getMessage().equals("database already closed"))) {
-                System.err.println("Error closing DB " + dbFile.getPath());
-            }
-        }
-        tracker.reset();
-        super.tearDown();
-    }
-
-    public void testDatabase() throws Exception {
-        // db closed
-        Database db2 = new Database();
-        db.close();
-        db2 = new Database();
-        db2.open(dbFile.getPath(), 0);
-        db2.close();
-        db.open(dbFile.getPath(), 0);
-        //db is open
-        db2.open(dbFile.getPath(), 0);
-        db2.close();
-    }
-
-    public void testOpen() throws Exception {
-        db.close();
-        db.open(dbFile.getPath(), 0);
-        // open second db while db1 still open
-        Database db2 = new Database();
-        db2.open(dbFile.getPath(), 0);
-        db2.open(dbFile.getPath(), 0);
-        db2.close();
-        // open non db file
-        try {
-            URL file = OldDatabaseTest.class.getResource("/blob.c");
-            db2.open(file.getPath(), 0);
-            fail("Should not be able to open non db file");
-        } catch (SQLite.Exception e) {
-            assertEquals("unknown error in open", e.getMessage());
-        }
-    }
-
-    public void testOpen_aux_file() {
-        File temp = null;
-        try {
-            db.open_aux_file("");
-            fail("open should fail");
-        } catch (Exception e) {
-            assertEquals("unsupported", e.getMessage());
-        }
-
-     /*
-        try {
-            temp = File.createTempFile("openAuxMethod", ".db");
-            db.open_aux_file("");
-            db.exec("create table AUX_TABLE", null);
-            db.close();
-        } catch (Exception e) {
-            temp.delete();
-            fail("Error handling temporary file "+e.getMessage());
-            e.printStackTrace();
-        } catch (IOException e) {
-            temp.delete();
-            fail("Could not create temporary File");
-            e.printStackTrace();
-        }
-        try {
-            db.open(dbFile.getPath(),0);
-            db.exec("select * from AUX_TABLE", null);
-            fail("Statement should fail");
-        } catch (Exception e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-
-        temp.delete();
-        */
-    }
-
-    public void testClose() throws Exception {
-        try {
-            db.close();
-            db.get_table("test");
-            fail();
-        } catch (Exception e) {
-            assertTrue(e.getMessage().equals("database already closed"));
-            try {
-                db.open(dbFile.getPath(), 0);
-            } catch (Exception e1) {
-                fail("Database object could not be reopened after 'close': "
-                        + e.getMessage());
-                e1.printStackTrace();
-            }
-        }
-
-        try {
-            db.close();
-            db.close();
-            fail();
-        } catch (Exception e) {
-            assertTrue(e.getMessage().equals("database already closed"));
-            db.open(dbFile.getPath(), 0);
-        }
-    }
-
-    public void testExecStringCallback() throws Exception {
-        TableResult res = new TableResult();
-        db.exec("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                + " VALUES(1, 10, 20)", null);
-        db.exec("select * from " + DatabaseCreator.SIMPLE_TABLE1, res);
-        db.exec("delete from " + DatabaseCreator.SIMPLE_TABLE1 + " where 1", null);
-        String row[] = (String[]) res.rows.elementAt(0);
-        assertEquals(Integer.parseInt(row[0]), 1);
-        assertEquals(Integer.parseInt(row[1]), 10);
-        assertEquals(Integer.parseInt(row[2]), 20);
-    }
-
-    public void testExecStringCallbackStringArray() throws Exception {
-        TableResult res = new TableResult();
-        String args[] = new String[1];
-        args[0] = "table";
-        db.exec("select name from sqlite_master where type = '%q';", res, args);
-        String[] s = (String[]) res.rows.elementAt(0);
-        assertEquals(s[0], DatabaseCreator.SIMPLE_TABLE1);
-
-        try {
-            db.exec("select name from sqlite_master where type = ", res, args);
-            fail("Testmethod should fail");
-        } catch (Exception e) {
-            // Ok
-        }
-    }
-
-    public void testLast_insert_rowid() throws Exception {
-        assertEquals(0, db.last_insert_rowid());
-        db.exec("create table TEST5(id integer, firstname text, lastname text);", null);
-        db.exec("insert into TEST5 values (1,'James','Bond');", null);
-        db.exec("insert into TEST5 values (2,'Fiona','Apple');", null);
-        assertEquals(2, db.last_insert_rowid());
-        assertEquals(db.last_insert_rowid(), db.last_insert_rowid());
-
-        db.exec("drop table TEST5;", null);
-        assertEquals(2, db.last_insert_rowid());
-    }
-
-    /**
-     * Reason for failure unknown: Database should be locked. Specification
-     * of interrupt is scarce.
-     */
-    public void testInterrupt() throws Exception, SQLException {
-        ThreadPool threadPool = new ThreadPool(numThreads);
-
-        // initialization
-        ResultSet userTabs;
-        userTabs = conn.getMetaData().getTables(null, null, null, null);
-        while (userTabs.next()) {
-            String tableName = userTabs.getString("TABLE_NAME");
-            if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
-                statement.execute(DatabaseCreator.DROP_TABLE1);
-            }
-        }
-        db.exec(DatabaseCreator.CREATE_TABLE3, null);
-        db.exec(DatabaseCreator.CREATE_TABLE1, null);
-
-        int id1 = numOfRecords - 3;
-        threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
-        // should not be able to do any other insertions since task 1 holds lock
-        int id2 = numOfRecords + 3;
-        threadPool
-                .runTask(createTask2Interrupt(id2, dbFile.getPath(), tracker));
-
-        threadPool.join();
-
-        List<String> errors = tracker.getErrors();
-        System.out.println("Last error: " + db.error_message());
-        if (errors.size() > 0) {
-            assertEquals(errors.get(0), db.error_string(Constants.SQLITE_LOCKED));
-            for (String s : errors) {
-                Logger.global.info("INTERRUPT Error: " + s);
-            }
-
-        } else {
-            fail("Should have one exception: database should be locked.");
-        }
-
-        // reset
-        db.exec("delete from " + DatabaseCreator.TEST_TABLE1 + " where 1", null);
-        db.exec("delete from " + DatabaseCreator.TEST_TABLE3 + " where 1", null);
-    }
-
-    /**
-     * Returns wrong number for updates: returns value > 1 for select.
-     */
-    public void testChanges() throws Exception {
-        TableResult res = new TableResult();
-        assertTrue(db.changes() == 0);
-        db.exec("INSERT INTO " + DatabaseCreator.SIMPLE_TABLE1
-                + " VALUES(2, 5, 7);", null);
-        int rows = (int) db.changes();
-        assertEquals(1,db.changes());
-        db.exec("update " + DatabaseCreator.SIMPLE_TABLE1
-                + " set speed = 7, size= 5 where id = 2;", null);
-        assertEquals(1,db.changes());
-        db.exec("select * from " + DatabaseCreator.SIMPLE_TABLE1, res);
-        assertEquals(0,db.changes());
-        db.exec("INSERT INTO " + DatabaseCreator.SIMPLE_TABLE1
-                + " VALUES(8, 5, 7);", null);
-        db.exec("Update "+DatabaseCreator.SIMPLE_TABLE1+" set speed = 10;",null);
-        assertTrue(db.changes() > 2);
-    }
-
-    /**
-     * method test fails once in a while. Cannot be sure that exception is
-     * thrown in every test execution.
-     */
-    public void testBusy_handler() throws SQLException, Exception {
-        TestBusyHandler bh = new TestBusyHandler();
-        db.busy_handler(bh);
-        int counter = 0;
-        ThreadPool threadPool = new ThreadPool(numThreads);
-
-        // initialization
-        ResultSet userTabs;
-        userTabs = conn.getMetaData().getTables(null, null, null, null);
-        while (userTabs.next()) {
-            String tableName = userTabs.getString("TABLE_NAME");
-            if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
-                statement.execute(DatabaseCreator.DROP_TABLE1);
-            }
-        }
-        db.exec(DatabaseCreator.CREATE_TABLE3, null);
-        db.exec(DatabaseCreator.CREATE_TABLE1, null);
-
-
-        try {
-            conn.setAutoCommit(false);
-            int id1 = numOfRecords - 3;
-            threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
-            int id2 = numOfRecords + 3;
-            threadPool.runTask(createTask2(id2, dbFile.getPath(), tracker));
-            int oldID = 5;
-            int newID = 100;
-            threadPool.runTask(createTask3(oldID, dbFile.getPath(), newID,
-                    tracker));
-
-            threadPool.join();
-
-            List<String> errors = tracker.getErrors();
-            if (errors.size() > 0) {
-//                 assertEquals(errors.get(0),
-//                 db.error_string(Constants.SQLITE_LOCKED));
-                for (String s: errors) {
-                  System.out.println("Round 2 Error: "+s);
-              }
-            } else {
-                fail("No error happened");
-            }
-
-            // reset
-
-
-            db.exec("delete from " + DatabaseCreator.TEST_TABLE1 + " where 1",
-                    null);
-            db.exec("delete from " + DatabaseCreator.TEST_TABLE3 + " where 1",
-                            null);
-//
-//            // increase timeout for retry
-//            db.busy_timeout(1000);
-//            db.busy_handler(bh);
-//            tracker.reset();
-
-//            threadPool = new ThreadPool(numThreads);
-//
-//            threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
-//            threadPool.runTask(createTask2(id2, dbFile.getPath(), tracker));
-//
-//            threadPool.join();
-//
-//            errors = tracker.getErrors();
-//            if (errors.size() > 0) {
-//                // assertEquals(errors.get(0),
-//                // db.error_string(Constants.SQLITE_LOCKED));
-//                for (String s: errors) {
-//                    System.out.println("Round 2 Error"+s);
-//                }
-//            } else {
-//                // ok
-//                System.out.println("BUSY: No Error!");
-//            }
-//
-//
-        } finally {
-            conn.setAutoCommit(true);
-            db.exec(DatabaseCreator.DROP_TABLE1, null);
-            db.exec(DatabaseCreator.DROP_TABLE3, null);
-        }
-    }
-
-    /**
-     * test fails. Cannot be sure that exception is thrown every time.
-     * Database does not lock values.
-     */
-    public void testBusy_timeout() throws Exception, SQLException {
-        int counter = 0;
-        ThreadPool threadPool = new ThreadPool(numThreads);
-
-        // initialization
-        ResultSet userTabs = conn.getMetaData().getTables(null, null, null, null);
-        while (userTabs.next()) {
-            String tableName = userTabs.getString("TABLE_NAME");
-            if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
-                statement.execute(DatabaseCreator.DROP_TABLE1);
-            }
-        }
-        db.exec(DatabaseCreator.CREATE_TABLE3, null);
-        db.exec(DatabaseCreator.CREATE_TABLE1, null);
-
-        // test run
-        try {
-            conn.setAutoCommit(false);
-
-//            DatabaseCreator.fillTestTable1(conn, numOfRecords);
-            // set to fail immediately if table is locked.
-            db.busy_handler(null);
-            db.busy_timeout(0);
-            int id1 = numOfRecords - 3;
-
-            threadPool.runTask(createTask2(id1, dbFile.getPath(), tracker));
-            int id2 = numOfRecords + 3;
-            threadPool.runTask(createTask1(id2, dbFile.getPath(), tracker));
-            int oldID = 5;
-            int newID = 100;
-            threadPool.runTask(createTask3(oldID, dbFile.getPath(), newID,
-                    tracker));
-
-            threadPool.join();
-
-            List<String> errors = tracker.getErrors();
-            assertTrue("No error occurred on DB but should have",errors.size() > 0);
-
-            assertEquals(errors.get(0),
-            db.error_string(Constants.SQLITE_LOCKED));
-            assertEquals(errors.get(0), "database is locked");
-
-            // reset
-
-            db.exec("delete from " + DatabaseCreator.TEST_TABLE1 + " where 1",
-                    null);
-            db.exec("delete from " + DatabaseCreator.TEST_TABLE3 + " where 1",
-                            null);
-
-            // increase timeout for retry
-            db.busy_timeout(10000);
-            db.busy_handler(null);
-            tracker.reset();
-            threadPool = new ThreadPool(numThreads);
-
-            threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
-            threadPool.runTask(createTask2(id2, dbFile.getPath(), tracker));
-
-            threadPool.join();
-
-            errors = tracker.getErrors();
-            if (errors.size() > 0) {
-                fail("busy timeout should prevent from lock exception!");
-                for (String s: errors) {
-                    System.out.println("Round 2 Error"+s);
-                }
-            } else {
-                // ok
-            }
-        } finally {
-            conn.setAutoCommit(true);
-            // cleanup
-            db.exec(DatabaseCreator.DROP_TABLE1, null);
-            db.exec(DatabaseCreator.DROP_TABLE3, null);
-        }
-    }
-
-    public void testGet_tableString() throws Exception {
-        TableResult emptyTable = new TableResult();
-        //select from empty table
-        TableResult res = db.get_table("select * from " + DatabaseCreator.SIMPLE_TABLE1);
-        assertEquals(res.toString(), emptyTable.toString());
-        //fill table-> t
-//        DatabaseCreator.fillSimpleTable1(conn);
-//        res = db.get_table("select * from "
-//                + DatabaseCreator.SIMPLE_TABLE1);
-//        assertFalse(emptyTable.toString().equals(res.toString()));
-
-        db.exec("insert into " + DatabaseCreator.SIMPLE_TABLE1 + " VALUES(1, 10, 20)", null);
-        res = db.get_table("select * from " + DatabaseCreator.SIMPLE_TABLE1);
-        db.exec("delete from " + DatabaseCreator.SIMPLE_TABLE1
-                + " where 1", null);
-        String row[] = (String[]) res.rows.elementAt(0);
-        assertEquals(Integer.parseInt(row[0]), 1);
-        assertEquals(Integer.parseInt(row[1]), 10);
-        assertEquals(Integer.parseInt(row[2]), 20);
-    }
-
-    public void testGet_tableStringStringArray() throws Exception {
-        String args[] = new String[1];
-        args[0] = "table";
-        String argsFail[] = new String[1];
-        try {
-            db.get_table("select name from sqlite_master where type = ", argsFail);
-            fail("Testmethod should fail");
-        } catch (Exception e) {
-        }
-
-        TableResult res = db.get_table(
-                "select name from sqlite_master where type = '%q'",
-                args);
-        String[] s = (String[]) res.rows.elementAt(0);
-        assertEquals(s[0], DatabaseCreator.SIMPLE_TABLE1);
-    }
-
-    public void testGet_tableStringStringArrayTableResult() throws Exception {
-        String args[] = new String[1];
-        String argsFail[] = new String[1];
-        TableResult res = new TableResult();
-        TableResult defaultTableRes = new TableResult();
-        args[0] = "table";
-
-        try {
-            db.get_table("select name from sqlite_master where type = '%q'", argsFail, res);
-            assertEquals(defaultTableRes.toString(), res.toString());
-        } catch (Exception e) {
-            db.get_table("select name from sqlite_master where type = '%q'", args, res);
-            String[] s = (String[]) res.rows.elementAt(0);
-            assertEquals(s[0], DatabaseCreator.SIMPLE_TABLE1);
-            System.out.println("DatabaseTest.testGet_tableStringStringArrayTableResult() "
-                    + Arrays.toString(res.types));
-        }
-    }
-
-    public void testComplete() {
-        assertFalse(db.complete("create"));
-        assertTrue(db.complete("create table TEST (res double);"));
-    }
-
-    public void testVersion() {
-        String version = db.version();
-        if (version != null) {
-            assertTrue(Integer.parseInt(db.version().substring(0, 1)) > 0);
-            assertEquals(db.version(), db.version());
-        } else {
-            fail("DB version info missing");
-        }
-    }
-
-    public void testDbversion() throws Exception {
-        String verNo = "";
-        try {
-            verNo = db.dbversion();
-            db.close();
-            assertEquals(db.dbversion(),"unknown");
-            db.open(dbFile.getPath(), 0);
-            assertEquals(verNo, db.dbversion());
-        } catch (Exception e) {
-            db.open(dbFile.getPath(), 0);
-        }
-
-        assertTrue(Integer.parseInt(verNo.substring(0, 1))>= 3 );
-
-    }
-
-    public void testCreate_function() throws Exception {
-        double input = 1.0;
-        db.exec("create table TEST (res double)", null);
-        db.exec("insert into TEST values (" + Double.toString(input) + ")",
-                null);
-        TableResult res = new TableResult();
-        Function sinFunc = (Function) new SinFunc();
-        db.create_function("sin", 1, sinFunc);
-        db.exec("select sin(res) from TEST WHERE res = "
-                + Double.toString(input), res);
-        String row[] = (String[]) res.rows.elementAt(0);
-        String val = row[0];
-        double sinusVal = Double.parseDouble(val);
-        double funcVal = Math.sin(input);
-
-        assertTrue(Math.round(funcVal) == Math.round(sinusVal));
-    }
-
-    /**
-     * Aggregation function not called.
-     */
-    public void testCreate_aggregate() throws Exception {
-        TestTrace t = new TestTrace();
-        MockFunction aggFunction = new MockFunction();
-        db.exec("create table TEST(id integer, firstname text, lastname text)", null);
-        db.exec("insert into TEST values(3, 'James', 'Bond'); ", null);
-        db.exec("insert into TEST values(4, 'Fiona', 'Apple'); ", null);
-        db.trace((Trace) t);
-        db.create_aggregate("myaggfunc", 1, aggFunction);
-        db.function_type("myaggfunc", Constants.SQLITE3_TEXT);
-        db.exec("PRAGMA show_datatypes = on", null);
-
-        assertFalse(aggFunction.functionCalled);
-        assertFalse(aggFunction.stepCalled);
-        assertFalse(aggFunction.lastStepCalled);
-        db.exec("select myaggfunc(TEST.firstname) from TEST", t);
-        assertTrue(aggFunction.stepCalled);
-        assertTrue(aggFunction.lastStepCalled);
-        assertTrue(aggFunction.functionCalled);
-
-        assertEquals("James Fiona ",aggFunction.getAggValue());
-        db.exec("drop table TEST", null);
-
-        try {
-            db.create_aggregate("myaggfunc", 0, null);
-        } catch (Throwable e) {
-            assertEquals("null SQLite.Function not allowed",e.getMessage());
-        }
-
-          try {
-            db.create_aggregate("myaggfunc", 0, aggFunction);
-        } catch (Throwable e) {
-            assertEquals("wrong number of arguments to function myaggfunc()",e.getMessage());
-        }
-    }
-
-    public void testFunction_type() throws Exception {
-        double input = 1.0;
-        TableResult res = new TableResult();
-        Function sinFunc = (Function) new SinFunc();
-
-        db.exec("PRAGMA show_datatypes = on", null);
-        db.exec("create table TEST (res double)", null);
-        db.exec("insert into TEST values (" + Double.toString(input) + ")",
-                null);
-
-        db.create_function("sin", 1, sinFunc);
-        db.function_type("sin", Constants.SQLITE_FLOAT);
-        res = db.get_table("select sin(res) from TEST WHERE res = "
-                + Double.toString(input));
-
-        String row[] = (String[]) res.rows.elementAt(0);
-        String val = row[0];
-        assertTrue("double".equalsIgnoreCase(res.types[0]));
-        assertSame(Math.round(Math.sin(input)), Math.round(Double.parseDouble(val)));
-
-        // function determines return type: test that Double type is returned.
-        db.function_type("sin", Constants.SQLITE_BLOB);
-        Stmt s = db.prepare("select sin(res) from TEST WHERE res = ?");
-        s.bind(1, input);
-        s.step();
-
-        res = db.get_table("select sin(res) from TEST WHERE res = "
-                + Double.toString(input));
-        assertTrue("double".equalsIgnoreCase(res.types[0]));
-        row = (String[]) res.rows.elementAt(0);
-        val = row[0];
-        assertSame(Math.round(Math.sin(input)), Math.round(Double.parseDouble(val)));
-    }
-
-    public void testLast_error() {
-        assertEquals(db.last_error(), Constants.SQLITE_OK);
-        try {
-            db.exec("create table TEST (res double)",null);
-            db.exec("create table TEST (res double)",null);
-            fail("Error should have happened");
-        } catch (Exception e) {
-            assertEquals(db.last_error(),db.last_error());
-            assertEquals(db.last_error(),Constants.SQLITE_ERROR);
-        }
-    }
-
-    public void testSet_last_error() {
-       assertEquals(db.last_error(), Constants.SQLITE_OK);
-       try {
-           db.exec("sel from test;", null);
-       } catch (Exception e) {
-           assertEquals(Constants.SQLITE_ERROR,db.last_error());
-       }
-    }
-
-    public void testError_message() {
-        String statement = "create table TEST (res double)";
-        try {
-            db.exec(statement,null);
-            db.exec(statement,null);
-            fail("DB Error expected");
-        } catch (Exception e) {
-            String dbError = db.error_message();
-            assertTrue(e.getMessage().equals(dbError));
-
-        }
-    }
-
-    public void testError_string() {
-        TestTrace t = new TestTrace();
-        assertEquals(db.last_error(), Constants.SQLITE_OK);
-        String errorString = db.error_string(Constants.SQLITE_ERROR);
-        try {
-            db.trace((Trace) t);
-            db.exec("create table TEST (res double)", t);
-            db.exec("create table TEST (res double)", t);
-        } catch (Exception e) {
-            assertEquals(db.last_error(), Constants.SQLITE_ERROR);
-            if (db.is3()) {
-                assertEquals("Unsupported Method (sqlite 3): error_string", db
-                        .error_string(db.last_error()), errorString);
-            }
-        }
-    }
-
-    /**
-     * ASCII encoding does not work: a UTF encoded val is returned. Spec is not
-     * sufficient. Might be that test impl is wrong or String constructor for
-     * the ASCII encoding.
-     */
-    public void testSet_encoding() throws UnsupportedEncodingException, Exception {
-        String input = "\u00bfMa\u00f1ana\u003f"; // ?Manana?
-        TableResult res = new TableResult();
-        String refOutput = null;
-        Stmt stat = null;
-
-        // DB setup
-        db.exec("create table encodingTest (encoded text DEFAULT NULL);",
-                null);
-        stat = db
-                .prepare("insert into encodingTest(encoded) values(:one);");
-        stat.bind(1, input);
-        stat.step();
-        // stat.close();
-        db.exec("select * from encodingTest;", res);
-        String[] encInput = (String[]) res.rows.elementAt(0);
-        String output = encInput[0];
-        assertEquals(input, output);
-        // db.exec("delete from encodingTest where 1", null);
-
-     // tests for different encoding schemes
-        String[] charsetNames = {"UTF-8", "UTF-16", "UTF-16BE", "UTF-16LE"};
-        for (int i = 0; i < charsetNames.length; i++) {
-            byte[] encInputBytes = input.getBytes(charsetNames[i]);
-            db.set_encoding(charsetNames[i]);
-            db.exec("select * from encodingTest;", res);
-            String[] encOutput = (String[]) res.rows.elementAt(0);
-            String inputAsString = new String(encInputBytes,charsetNames[i]);
-            assertEquals(inputAsString, encOutput[0]);
-        }
-
-        // Default tests
-        db.set_encoding("UTF-16");
-        db.exec("select * from encodingTest;", res);
-        String[] encOutput1 = (String[]) res.rows.elementAt(0);
-        assertEquals("Got "+encOutput1[0]+" as UTF-16",input,encOutput1[0]);
-
-        db.set_encoding("US-ASCII");
-        db.exec("select * from encodingTest;", res);
-        String[] encOutput2 = (String[]) res.rows.elementAt(0);
-        assertEquals(new String(input.getBytes(),"US-ASCII"),encOutput2[0]);
-
-        // DB teardown
-        stat.close();
-        db.exec("delete from encodingTest", null);
-
-        // Default tests
-        try {
-            db.set_encoding("");
-            fail("invalid input should fail");
-        } catch (Exception e) {
-            //ok
-        }
-    }
-
-    /**
-     * Callback never made for authorization. Results of private table are
-     * returned withouth furhter checks.
-     *
-     * Test fails -> implemented correctly?
-     */
-    public void testSet_authorizer() throws Exception {
-        TableResult resPriv = null;
-        TableResult resPub = null;
-        TableResult emptyTable = new TableResult();
-        String insertPublic = "insert into public_table values(1,2)";
-        String insertPrivate = "insert into private_table values(1,2)";
-        // prepare, authorizer is not activated yet
-        db.exec("create table public_table(c1 integer, c2 integer);", null);
-        db.exec("create table private_table(c1 integer, c2 integer);", null);
-        // inserts
-        db.exec(insertPublic, null);
-        db.exec(insertPrivate, null);
-        // selects
-        resPriv = db.get_table("select * from private_table");
-        resPub = db.get_table("select * from public_table");
-
-//        db.exec("delete from public_table where 1", null);
-//        TableResult emptyPubTable = db.exec("select * from public");
-
-        // set Authorizer (positive case): denies private table
-        AuthorizerCallback cb = new AuthorizerCallback();
-        db.set_authorizer(cb);
-        //select
-
-        db.exec("select * from private_table", cb);
-        assertTrue(cb.wasCalled());
-
-       /*
-        TableResult res = db.get_table("select * from private_table");
-        assertEquals(emptyTable.toString(),res.toString());
-        assertFalse(emptyTable.equals(resPriv));
-
-        res = db.get_table("select * from public_table");
-        assertEquals(resPub,res);
-        */
-
-        // Try insert
-        try {
-            db.exec(insertPublic, null);
-            fail("authorization failed");
-        } catch (Exception e) {
-        }
-
-        try {
-            db.exec(insertPrivate, null);
-            fail("authorization failed");
-        } catch (Exception e1) {
-            // ok
-        }
-    }
-
-    public void testTrace() throws Exception {
-        String stmt = "create table TEST (res double);";
-        TestTrace t = new TestTrace();
-        assertFalse(t.traceCalled);
-        assertEquals(db.last_error(),Constants.SQLITE_OK);
-        db.trace((Trace) t);
-        db.exec(stmt,t);
-        assertTrue(t.traceCalled);
-        assertEquals(t.getTrace(),stmt);
-
-        try {
-            db.close();
-            db.exec(stmt,t);
-            fail("Exception Expected");
-        } catch (Exception e) {
-            //ok
-        }
-    }
-
-    public void testCompileString() throws Exception {
-        db.compile("select name from sqlite_master;");
-        try {
-            db.compile("test");
-            fail("Compiling of inaccurate statement does not fail.");
-        } catch (Exception e) {
-        }
-    }
-
-    public void testCompileStringStringArray() throws Exception {
-        String args[] = new String[1];
-        args[0] = "table";
-        db.compile("select name from sqlite_master where type = '%q';",args);
-
-        try {
-            db.compile("test",null);
-            fail("Compiling of inaccurate statement does not fail.");
-        } catch (Exception e) {
-        }
-    }
-
-    public void testPrepare() throws Exception {
-        Stmt st = null;
-        Stmt st2 = null;
-        // test empty statement
-        try {
-            st = db.prepare("");
-            assertEquals(0, st.bind_parameter_count());
-            st.step();
-            fail("stmt should not be prepared");
-        } catch (Exception e) {
-            assertEquals("stmt already closed", e.getMessage());
-        }
-
-        // test statement with unbound arguments
-        try {
-            st2 = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                    + " values (:one,:two,:three)");
-            assertEquals(3, st2.bind_parameter_count());
-            assertEquals(3, st2.bind_parameter_index(":three"));
-            assertEquals(":two", st2.bind_parameter_name(2));
-        } finally {
-            st2.close();
-        }
-
-        try {
-            db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                    + " values(:one,:two,:three,:four);");
-        } catch (Exception e) {
-            assertEquals("table " + DatabaseCreator.SIMPLE_TABLE1
-                    + " has 3 columns but 4 values were supplied", e
-                    .getMessage());
-        }
-
-        try {
-            db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                    + " values(5, '10, 20);");
-        } catch (Exception e) {
-            assertEquals("unrecognized token: \"'10, 20);\"", e.getMessage());
-        }
-
-        try {
-            db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                    + " values(5, 10 20);");
-        } catch (Exception e) {
-            assertEquals("near \"20\": syntax error", e.getMessage());
-        }
-
-    }
-
-    /**
-     * Not supported.
-     */
-    public void testOpen_blob() throws Exception, java.lang.Exception {
-        Stmt statement2;
-        Blob blobInput = new Blob();
-
-        // Create test input Blob
-        InputStream inStream = null;
-        byte[] in = {(byte) 1, (byte) 2, (byte) 3, (byte) 4};
-
-        // setup test input
-        db.exec("create table TEST (res blob)",null);
-        inStream = Class.forName(this.getClass().getName()).getResourceAsStream("/blob.c");
-        assertNotNull(inStream);
-
-        // insert byte array in db
-        statement2 = db.prepare("insert into TEST(res) values (?)");
-        statement2.bind(1, in);
-        statement2.step();
-        statement2.close();
-
-        // read from db
-        Blob blob = db.open_blob(dbFile.getPath(), "TEST", "res", 1, true);
-        if (blob == null) {
-            fail("Blob could not be retrieved");
-        }
-        //read from blob and compare values (positive case)
-        InputStream is = blob.getInputStream();
-
-        int i = 0;
-        int outByte = 0;
-        byte[] out = new byte[4];
-        while ((outByte = is.read()) > -1) {
-            out[i] = (byte) outByte;
-            i++;
-        }
-        is.close();
-
-        blob.close();
-
-        assertTrue(Arrays.equals(in, out));
-
-        //read from blob and compare values (default blob)
-        db.exec("insert into TEST values(zeroblob(128))", null);
-        Blob blob2 = db.open_blob(dbFile.getPath(), "TEST", "res", 2, true);
-        is = blob2.getInputStream();
-        for (i = 0; i < 128; i++)  {
-           assertEquals(0, is.read());
-        }
-        is.close();
-    }
-
-    public void testIs3() {
-        int ver = Integer.parseInt(db.version().substring(0,1));
-        if (db.is3()) {
-            assertTrue( ver == 3);
-        } else {
-            assertTrue(ver != 3);
-        }
-    }
-
-    public void testProgress_handler() throws Exception {
-        int inputVal = 3;
-        TestProgressHandler prog = new TestProgressHandler();
-        db.exec("create table TEST5(id integer, firstname text, lastname text)",null);
-        Vm vm = db.compile("select * from TEST5; "
-                + "insert into TEST5 values(3, 'James', 'Bond'); "
-                + "delete from TEST5 where id = 3; "
-                + "select * from TEST5");
-        int stmt = 0;
-        do {
-            ++stmt;
-            if (stmt > inputVal) {
-                db.progress_handler(inputVal, prog);
-            } else {
-                assertEquals(0, prog.getCounts());
-            }
-            while (vm.step(prog)) {
-            }
-        } while (vm.compile());
-        assertEquals(inputVal,prog.getCounts());
-
-        // Boundary value test
-        inputVal = 0;
-        TestProgressHandler progBoundary = new TestProgressHandler();
-        db.progress_handler(inputVal, progBoundary);
-        Vm vm2 = db.compile("select * from TEST5; "
-                + "insert into TEST5 values(3, 'James', 'Bond'); "
-                + "delete from TEST5 where id = 3; "
-                + "select * from TEST5");
-        do {
-            vm2.step(progBoundary);
-        } while (vm2.compile());
-        assertEquals(inputVal, progBoundary.getCounts());
-
-        try {
-            db.exec("drop table TEST5",null);
-        } catch (Exception e) {
-            System.out.println(e.getMessage());
-            e.printStackTrace();
-        }
-    }
-
-    class SinFunc implements Function {
-        public void function(FunctionContext fc, String args[]) {
-            Double d = new Double(args[0]);
-            fc.set_result(Math.sin(d.doubleValue()));
-        }
-        public void last_step(FunctionContext fc) {}
-        public void step(FunctionContext fc, String[] args) {}
-    }
-
-    class TestTrace implements Trace,Callback {
-
-        private StringBuffer buf = new StringBuffer();
-
-        public boolean traceCalled = false;
-
-        public String getTrace() {
-            return buf.toString();
-        }
-
-        public void trace(String stmt) {
-            traceCalled = true;
-            buf.append(stmt);
-        }
-
-        public void columns(String[] coldata) {}
-
-        public boolean newrow(String[] rowdata) {
-            return false;
-        }
-
-        public void types(String[] types) {}
-    }
-
-    class AuthorizerCallback implements Authorizer, Callback {
-
-        private boolean isAuthorizing = false;
-
-        public boolean wasCalled() {
-            return isAuthorizing;
-        }
-
-        public int authorize(int action, String arg1, String arg2, String arg3,
-                String arg4) {
-            Logger.global.info("DB authorization callback " + action + " " + arg1 + " " + arg2 + " "
-                    + arg3 + " " + arg4 + " ");
-            this.isAuthorizing = true;
-            if (action != Constants.SQLITE_SELECT || arg1.contains("private_table")) {
-                return Constants.SQLITE_DENY;
-            } else {
-                return Constants.SQLITE_OK;
-            }
-        }
-
-        public void columns(String[] coldata) {}
-
-        public boolean newrow(String[] rowdata) {
-            return false;
-        }
-
-        public void types(String[] types) {}
-
-    }
-
-    class TestBusyHandler implements BusyHandler, Callback {
-
-        public boolean busy(String table, int count) {
-            return true;
-        }
-
-        public void columns(String[] coldata) {}
-
-        public boolean newrow(String[] rowdata) {
-            return false;
-        }
-
-        public void types(String[] types) {}
-    }
-
-    class TestProgressHandler implements ProgressHandler, Callback {
-
-        private boolean progressed = false;
-
-        private int counter = 0;
-
-        public int getCounts() {
-            return counter;
-        }
-
-        public boolean progress() {
-            this.progressed = true;
-            counter++;
-            return true;
-        }
-
-        public void columns(String[] coldata) {}
-
-        public boolean newrow(String[] rowdata) {
-            return false;
-        }
-
-        public void types(String[] types) {}
-    }
-
-    /**
-     * This method creates a Runnable that executes insert operation for the first table
-     */
-    private static Runnable createTask2Interrupt(final int id,
-            final String dbName, final ErrorTracker errorTracker) {
-        return new Runnable() {
-            public void run() {
-                Database db = new Database();
-                try {
-                    String value = DatabaseCreator.defaultString + id;
-
-                    db.open(dbName, 0);
-                    String insertQuery = "INSERT INTO "
-                            + DatabaseCreator.TEST_TABLE1
-                            + " (id, field1, field2, field3) VALUES(" + id
-                            + ", '" + value + "', " + id + ", " + id + ")";
-                    db.exec(insertQuery, null);
-                } catch (Exception e) {
-                    errorTracker.registerException(this, e);
-                    try {
-                        db.interrupt();
-                        db.exec("DELETE FROM " + DatabaseCreator.SIMPLE_TABLE1
-                                + " WHERE id=" + id, null);
-                    } catch (Exception e1) {
-                        errorTracker.registerException(this, e1);
-                    }
-                }
-            }
-        };
-    }
-
-    /**
-     * This method creates a Runnable that executes delete operation for the first table
-     */
-    private static Runnable createTask1(final int id, final String dbName,
-            final ErrorTracker errorTracker) {
-        return new Runnable() {
-            public void run() {
-                try {
-                    Database db = new Database();
-                    db.open(dbName, 0);
-                    db.exec("DELETE FROM "
-                            + DatabaseCreator.SIMPLE_TABLE1 + " WHERE id=" + id, null);
-                } catch (Exception e) {
-                    errorTracker.registerException(this, e);
-                }
-            }
-        };
-    }
-
-    /**
-     * This method creates a Runnable that executes insert operation for the first table
-     */
-    private static Runnable createTask2(final int id, final String dbName,
-            final ErrorTracker errorTracker) {
-        return new Runnable() {
-            public void run() {
-                try {
-                    String value = DatabaseCreator.defaultString + id;
-                    Database db = new Database();
-                    db.open(dbName, 0);
-                    String insertQuery = "INSERT INTO "
-                            + DatabaseCreator.TEST_TABLE1
-                            + " (id, field1, field2, field3) VALUES(" + id
-                            + ", '" + value + "', " + id + ", " + id + ")";
-                    db.exec(insertQuery, null);
-                } catch (Exception e) {
-                    errorTracker.registerException(this, e);
-
-                }
-            }
-        };
-    }
-
-    /**
-     * This method creates a Runnable that executes update operation for the one record of the first
-     * table
-     */
-    private static Runnable createTask3(final int oldID, final String dbName,
-            final int newID, final ErrorTracker errorTracker) {
-        return new Runnable() {
-            public void run() {
-                Database db = new Database();
-                try {
-                    db.open(dbName, 0);
-                    String value = DatabaseCreator.defaultString + newID;
-                    String updateQuery = "UPDATE "
-                            + DatabaseCreator.TEST_TABLE1 + " SET id=" + newID
-                            + ", field1='" + value + "', field2=" + newID
-                            + ", field3=" + newID + " WHERE id=" + oldID;
-                    db.exec(updateQuery, null);
-                } catch (Exception e) {
-                    errorTracker.registerException(this, e);
-                }
-            }
-        };
-    }
-
-    private class ErrorTracker {
-
-        private List<String> errors = new ArrayList<String>();
-
-        public void registerException(Runnable runnable, Exception e) {
-            System.out.println("Registered: " + e.getMessage());
-            errors.add(e.getMessage());
-        }
-
-        public List<String> getErrors() {
-            return errors;
-        }
-
-        public void reset() {
-            errors.clear();
-        }
-    }
-}
diff --git a/luni/src/test/java/libcore/sqlite/OldExceptionTest.java b/luni/src/test/java/libcore/sqlite/OldExceptionTest.java
deleted file mode 100644
index dddfd6b..0000000
--- a/luni/src/test/java/libcore/sqlite/OldExceptionTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.sqlite;
-
-import SQLite.Database;
-import SQLite.Exception;
-
-public final class OldExceptionTest extends OldSQLiteTest {
-
-    private Database db = null;
-
-    @Override public void setUp() throws java.lang.Exception {
-        super.setUp();
-        db = new Database();
-    }
-
-    public void testException() {
-        try {
-            db.open(dbFile.getName(), 0);
-        } catch (Exception e) {
-            assertNotNull(e);
-            assertNotNull(e.getMessage());
-        }
-    }
-}
diff --git a/luni/src/test/java/libcore/sqlite/OldFunctionContextTest.java b/luni/src/test/java/libcore/sqlite/OldFunctionContextTest.java
deleted file mode 100644
index 0924317..0000000
--- a/luni/src/test/java/libcore/sqlite/OldFunctionContextTest.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.sqlite;
-
-import SQLite.Database;
-import SQLite.Exception;
-import SQLite.Function;
-import SQLite.FunctionContext;
-import SQLite.Stmt;
-import SQLite.TableResult;
-import java.io.UnsupportedEncodingException;
-import java.sql.SQLException;
-import java.sql.Statement;
-import tests.support.DatabaseCreator;
-
-public final class OldFunctionContextTest extends OldSQLiteTest {
-
-    private Database db = null;
-
-    @Override public void setUp() throws java.lang.Exception {
-        super.setUp();
-        db = new Database();
-        db.open(dbFile.getPath(), 0);
-        Statement st = conn.createStatement();
-        st.execute(DatabaseCreator.CREATE_TABLE2);
-        st.execute(DatabaseCreator.CREATE_TABLE_SIMPLE1);
-        st.close();
-    }
-
-    public void testSet_resultString() throws Exception {
-        TestFCString testString = new TestFCString();
-        db.exec("insert into " + DatabaseCreator.TEST_TABLE2
-                + " (ftext) values ('TestInput')", null);
-        db.create_function("test", 1, testString);
-        TableResult res = db.get_table("select test(ftext) from "
-                + DatabaseCreator.TEST_TABLE2);
-        String row[] = (String[]) res.rows.elementAt(0);
-        String val = row[0];
-
-        assertEquals("TestInput", val);
-    }
-
-    public void testSet_resultInt() throws Exception {
-        TestFCInt testInt = new TestFCInt();
-        db.exec("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                + "  values (1,'" + testInt.intVal + "',3)", null);
-        db.create_function("testInt", 1, testInt);
-        TableResult res = db.get_table("select testInt(speed) from "
-                + DatabaseCreator.SIMPLE_TABLE1);
-        String row[] = (String[]) res.rows.elementAt(0);
-        String val = row[0];
-
-        assertEquals(testInt.intVal, Integer.parseInt(val));
-    }
-
-    public void testSet_resultDouble() throws Exception {
-        SinFunc testD = new SinFunc();
-        db.exec("insert into " + DatabaseCreator.TEST_TABLE2
-                + " (fdouble)  values (" + testD.testDouble + ")", null);
-        db.create_function("testDouble", 1, testD);
-        TableResult res = db.get_table("select testDouble(fdouble) from "
-                + DatabaseCreator.TEST_TABLE2);
-        String row[] = (String[]) res.rows.elementAt(0);
-        String val = row[0];
-
-        assertEquals(testD.testDouble, Double.parseDouble(val));
-
-        assertTrue(testD.functionCalled);
-    }
-
-    public void testSet_error() throws Exception {
-        TestFCError testError = new TestFCError();
-        SinFunc testD = new SinFunc();
-        db.exec("insert into " + DatabaseCreator.TEST_TABLE2
-                + " (fdouble)  values (" + testD.testDouble + ")", null);
-        db.create_function("testError", 1, testError);
-
-        try {
-        TableResult res = db.get_table("select testError(fdouble) from "
-                + DatabaseCreator.TEST_TABLE2);
-        fail("Should get Exception");
-        } catch (Exception e) {
-            assertEquals("error in step", e.getMessage());
-        }
-
-        assertFalse(testD.functionCalled);
-    }
-
-    public void testSet_resultByteArray() throws Exception, UnsupportedEncodingException {
-        Stmt st = null;
-        TestFCByteArray testBinArrayFnc = new TestFCByteArray();
-        String expected = "";
-        expected = "X'" + getHexString(testBinArrayFnc.byteVal) + "'";
-
-        // setup
-        db.exec("create table testBinaryData (binVal BINARY) ;", null);
-
-        try {
-        st = db.prepare("insert into testBinaryData values (?)");
-        st.bind(1, testBinArrayFnc.byteVal);
-        st.step();
-
-
-        db.create_function("testBinArray", 1, testBinArrayFnc);
-        TableResult res = db
-                .get_table("select testBinArray(binVal) from testBinaryData");
-
-        String row[] = (String[]) res.rows.elementAt(0);
-        String val = row[0];
-
-        assertTrue(expected.equalsIgnoreCase(val));
-
-        assertTrue(testBinArrayFnc.functionCalled);
-
-        } finally {
-            //teardown
-            db.exec("drop table testBinaryData;", null);
-        }
-    }
-
-    /**
-     * ZeroBlob not supported
-     */
-    public void testSet_result_zeroblob() throws Exception,
-            UnsupportedEncodingException {
-        Stmt st = null;
-        TestFCZeroBlob testZeroBlobFnc = new TestFCZeroBlob();
-        byte[] byteVal = {(byte) 1, (byte) 2, (byte) 3};
-
-
-        // setup
-        db.exec("create table testBinaryData (binVal BINARY) ;", null);
-
-        try {
-        st = db.prepare("insert into testBinaryData values (?)");
-        st.bind(1, byteVal);
-        st.step();
-
-
-        db.create_function("testZeroBlob", 0, testZeroBlobFnc);
-        TableResult res = db
-                .get_table("select testZeroBlob() from testBinaryData");
-        TableResult res2 = db.get_table("select zeroblob("
-                + testZeroBlobFnc.numBytes + ") from testBinaryData");
-
-        String row[] = (String[]) res.rows.elementAt(0);
-        String val = row[0];
-
-        assertNotNull(val);
-
-        assertEquals(((String[]) res2.rows.elementAt(0))[0], val);
-        assertTrue(testZeroBlobFnc.functionCalled);
-
-        } finally  {
-         // teardown
-            db.exec("drop table if exists testBinaryData;", null);
-        }
-    }
-
-    /**
-     * Test Method results in a segmentation fault
-     */
-    public void testCount() throws SQLException, Exception {
-        TestFCCount countTest = new TestFCCount();
-        int inputCount = 10;
-
-        assertFalse(countTest.functionCalled);
-
-        DatabaseCreator.fillTestTable2(conn, inputCount);
-        db.create_function("testCount", 0, countTest);
-        // the invokation of testCount leads to a Segmentation fault
-        /*
-        TableResult res = db
-                .get_table("select testCount() from "+DatabaseCreator.TEST_TABLE2);
-
-        String row[] = (String[]) res.rows.elementAt(0);
-        String val = row[0];
-
-        assertTrue(countTest.functionCalled);
-        assertEquals(inputCount,Integer.parseInt(val));
-        */
-
-    }
-
-    class TestFCError implements Function {
-        public boolean functionCalled = false;
-        public String errorMsg = "FunctionError";
-
-        public void function(FunctionContext fc, String args[]) {
-            functionCalled = true;
-            fc.set_error(errorMsg);
-        }
-
-        public void last_step(FunctionContext fc) {}
-        public void step(FunctionContext fc, String[] args) {}
-    }
-
-    class TestFCCount implements Function {
-        public boolean functionCalled = false;
-        public int noOfRows = 0;
-
-        public void function(FunctionContext fc, String args[]) {
-            functionCalled = true;
-            noOfRows = fc.count();
-            fc.set_result(noOfRows);
-        }
-
-        public void last_step(FunctionContext fc) {}
-        public void step(FunctionContext fc, String[] args) {}
-    }
-
-    class TestFCZeroBlob implements Function {
-        public int numBytes = 16;
-        public boolean functionCalled = false;
-
-        public void function(FunctionContext fc, String args[]) {
-            functionCalled = true;
-            fc.set_result_zeroblob(numBytes);
-        }
-
-        public void last_step(FunctionContext fc) {}
-        public void step(FunctionContext fc, String[] args) {}
-    }
-
-    class TestFCString implements Function {
-        public String testString = "TestString";
-        public boolean functionCalled;
-
-        public void function(FunctionContext fc, String args[]) {
-            assertNotNull(args);
-            functionCalled = true;
-            fc.set_result(args[0]);
-        }
-
-        public void last_step(FunctionContext fc) {}
-        public void step(FunctionContext fc, String[] args) {}
-    }
-
-    class TestFCInt implements Function {
-        public int intVal = Integer.MAX_VALUE;
-        public boolean functionCalled;
-
-        public void function(FunctionContext fc, String args[]) {
-            assertNotNull(args);
-            functionCalled = true;
-            fc.set_result(Integer.parseInt(args[0]));
-        }
-
-        public void last_step(FunctionContext fc) {}
-        public void step(FunctionContext fc, String[] args) {}
-    }
-
-    class TestFCByteArray implements Function {
-        public byte[] byteVal = {(byte)  1, (byte) 2, (byte) 3};
-        public boolean functionCalled;
-
-        public void function(FunctionContext fc, String args[]) {
-            assertNotNull(args);
-            functionCalled = true;
-            fc.set_result(args[0].getBytes());
-        }
-
-        public void last_step(FunctionContext fc) {}
-        public void step(FunctionContext fc, String[] args) {}
-    }
-
-    class SinFunc implements Function {
-        public Double testDouble = 3.0;
-        public boolean functionCalled = false;
-
-        public void function(FunctionContext fc, String args[]) {
-            Double d = new Double(args[0]);
-            functionCalled = true;
-            fc.set_result(d.doubleValue());
-        }
-
-        public void last_step(FunctionContext fc) {}
-        public void step(FunctionContext fc, String[] args) {}
-    }
-
-    static final byte[] HEX_CHAR_TABLE = {
-            (byte)'0', (byte)'1', (byte)'2', (byte)'3',
-            (byte)'4', (byte)'5', (byte)'6', (byte)'7',
-            (byte)'8', (byte)'9', (byte)'a', (byte)'b',
-            (byte)'c', (byte)'d', (byte)'e', (byte)'f'
-          };
-
-    public static String getHexString(byte[] raw)
-            throws UnsupportedEncodingException {
-        byte[] hex = new byte[2 * raw.length];
-        int index = 0;
-
-        for (byte b : raw) {
-            int v = b & 0xFF;
-            hex[index++] = HEX_CHAR_TABLE[v >>> 4];
-            hex[index++] = HEX_CHAR_TABLE[v & 0xF];
-        }
-        return new String(hex, "ASCII");
-    }
-}
diff --git a/luni/src/test/java/libcore/sqlite/OldJDBCDriverFunctionalTest.java b/luni/src/test/java/libcore/sqlite/OldJDBCDriverFunctionalTest.java
deleted file mode 100644
index 48eeab1..0000000
--- a/luni/src/test/java/libcore/sqlite/OldJDBCDriverFunctionalTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.sqlite;
-
-import java.io.File;
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.SQLException;
-
-/**
- * Tests the SQLite.JDBCDriver.
- */
-public class OldJDBCDriverFunctionalTest extends AbstractSqlTest {
-    private  File dbFile = null;
-    private String connectionURL = "empty";
-
-    @Override protected void tearDown() throws SQLException {
-        super.tearDown();
-        dbFile.delete();
-    }
-
-    @Override protected String getConnectionURL() {
-        if (connectionURL.equals("empty")) {
-            String tmp = System.getProperty("java.io.tmpdir");
-            File tmpDir = new File(tmp);
-            if (tmpDir.isDirectory()) {
-                try {
-                    dbFile = File.createTempFile("JDBCDriverFunctionalTest", ".db", tmpDir);
-                } catch (IOException e) {
-                    System.err.println("error creating temporary DB file.");
-                }
-                dbFile.deleteOnExit();
-            } else {
-                System.err.println("java.io.tmpdir does not exist");
-            }
-
-            connectionURL = "jdbc:sqlite:/" + dbFile.getPath();
-        }
-
-        return connectionURL;
-    }
-
-    @Override protected String getDriverClassName() {
-        return "SQLite.JDBCDriver";
-    }
-
-    @Override protected int getTransactionIsolation() {
-        return Connection.TRANSACTION_SERIALIZABLE;
-    }
-}
diff --git a/luni/src/test/java/libcore/sqlite/OldJDBCDriverTest.java b/luni/src/test/java/libcore/sqlite/OldJDBCDriverTest.java
deleted file mode 100644
index ae06dc6..0000000
--- a/luni/src/test/java/libcore/sqlite/OldJDBCDriverTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.sqlite;
-
-import SQLite.JDBCDriver;
-import java.sql.Connection;
-import java.sql.Driver;
-import java.sql.DriverManager;
-import java.sql.DriverPropertyInfo;
-import java.sql.SQLException;
-
-
-public final class OldJDBCDriverTest extends OldJDBCDriverFunctionalTest {
-
-    /**
-     * The SQLite db file.
-     */
-    private JDBCDriver jDriver;
-
-    private Driver returnedDriver;
-
-    @Override public void setUp() throws java.lang.Exception {
-        super.setUp();
-        returnedDriver = DriverManager.getDriver(getConnectionURL());
-        if (returnedDriver instanceof JDBCDriver) {
-            this.jDriver = (JDBCDriver) returnedDriver;
-        }
-    }
-
-    public void testJDBCDriver() {
-        assertTrue(returnedDriver instanceof JDBCDriver);
-    }
-
-    public void testAcceptsURL() {
-        try {
-            if (this.jDriver != null) {
-                assertTrue(jDriver.acceptsURL(getConnectionURL()));
-            } else {
-                fail("no Driver available");
-            }
-        } catch (SQLException e) {
-            fail("Driver does not accept URL");
-            e.printStackTrace();
-        }
-    }
-
-    public void testConnect() {
-        try {
-            if (this.jDriver != null) {
-                Connection c = jDriver.connect(getConnectionURL(), null);
-                assertFalse(c.isClosed());
-                DriverManager.getConnection(getConnectionURL());
-            } else {
-                fail("no Driver available");
-            }
-        } catch (SQLException e) {
-            fail("Driver does not connect");
-            e.printStackTrace();
-        }
-    }
-
-    public void testGetMajorVersion() {
-        if (this.jDriver != null) {
-            assertTrue(jDriver.getMajorVersion() > 0);
-        } else {
-            fail("no Driver available");
-        }
-    }
-
-   public void testGetMinorVersion() {
-        if (this.jDriver != null) {
-            assertTrue(jDriver.getMinorVersion() > 0);
-        } else {
-            fail("no version information available");
-        }
-    }
-
-   public void testGetPropertyInfo() throws SQLException {
-        DriverPropertyInfo[] info = null;
-       if (this.jDriver != null) {
-           info = jDriver.getPropertyInfo(getConnectionURL(), null);
-           assertNotNull(info);
-           assertTrue(info.length > 0);
-       } else {
-           fail("no Driver available");
-       }
-
-        assertNotNull(info);
-
-    }
-
-    public void testJdbcCompliant() {
-        if (this.jDriver != null) {
-            assertFalse(jDriver.jdbcCompliant());
-        } else {
-            fail("no version information available");
-        }
-    }
-}
diff --git a/luni/src/test/java/libcore/sqlite/OldSQLiteTest.java b/luni/src/test/java/libcore/sqlite/OldSQLiteTest.java
deleted file mode 100644
index e6b7f22..0000000
--- a/luni/src/test/java/libcore/sqlite/OldSQLiteTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.sqlite;
-
-import java.io.File;
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.util.logging.Logger;
-import junit.framework.TestCase;
-
-public abstract class OldSQLiteTest extends TestCase {
-
-    public static Connection conn;
-
-    public static File dbFile = null;
-
-    @Override public void setUp() throws Exception {
-        String tmp = System.getProperty("java.io.tmpdir");
-        File tmpDir = new File(tmp);
-        try {
-            if (tmpDir.isDirectory()) {
-                dbFile = File.createTempFile("sqliteTest", ".db", tmpDir);
-                dbFile.deleteOnExit();
-            } else {
-                System.out.println("ctsdir does not exist");
-            }
-
-            Class.forName("SQLite.JDBCDriver").newInstance();
-
-            if (!dbFile.exists()) {
-                Logger.global.severe("DB file could not be created. Tests can not be executed.");
-            } else {
-                conn = DriverManager.getConnection("jdbc:sqlite:/" + dbFile.getPath());
-            }
-            assertNotNull("Error creating connection", conn);
-        } catch (IOException e) {
-            System.out.println("Problem creating test file in " + tmp);
-        }
-    }
-
-    @Override public void tearDown() throws java.lang.Exception {
-        if (!conn.isClosed()) {
-            conn.close();
-        }
-        super.tearDown();
-    }
-}
diff --git a/luni/src/test/java/libcore/sqlite/OldStmtTest.java b/luni/src/test/java/libcore/sqlite/OldStmtTest.java
deleted file mode 100644
index 4d379ed..0000000
--- a/luni/src/test/java/libcore/sqlite/OldStmtTest.java
+++ /dev/null
@@ -1,823 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.sqlite;
-
-import SQLite.Constants;
-import SQLite.Database;
-import SQLite.Stmt;
-import SQLite.TableResult;
-import java.sql.Connection;
-import tests.support.DatabaseCreator;
-import tests.support.Support_SQL;
-
-public class OldStmtTest extends OldSQLiteTest {
-
-    private Database db;
-    private Stmt st;
-
-    private static final String CREATE_ALL_TYPES = "create table type ("
-            + " BoolVal BOOLEAN,"
-            + " IntVal INT,"
-            + " LongVal LONG,"
-            + " Bint BIGINT,"
-            + " Tint TINYINT,"
-            + " Sint SMALLINT,"
-            + " Mint MEDIUMINT,"
-            + " IntegerVal INTEGER,"
-            + " RealVal REAL,"
-            + " DoubleVal DOUBLE,"
-            + " FloatVal FLOAT,"
-            + " DecVal DECIMAL,"
-            + " NumVal NUMERIC,"
-            + " charStr CHAR(20),"
-            + " dateVal DATE,"
-            + " timeVal TIME,"
-            + " TS TIMESTAMP,"
-            + " DT DATETIME,"
-            + " TBlob TINYBLOB,"
-            + " BlobVal BLOB,"
-            + " MBlob MEDIUMBLOB,"
-            + " LBlob LONGBLOB,"
-            + " TText TINYTEXT,"
-            + " TextVal TEXT,"
-            + " MText MEDIUMTEXT,"
-            + " LText LONGTEXT,"
-            + " MaxLongVal BIGINT,"
-            + " MinLongVal BIGINT,"
-            + " validURL URL,"
-            + " invalidURL URL);";
-
-    static final String INSERT_ALL_TYPES = "insert into type ("
-            + "BoolVal, IntVal, LongVal, Bint, Tint, Sint, Mint,IntegerVal, RealVal, DoubleVal, "
-            + "FloatVal, DecVal,NumVal, charStr, dateVal, timeVal, TS,DT, TBlob, BlobVal, MBlob, "
-            + "LBlob,TText, TextVal, MText, LText, MaxLongVal, MinLongVal, validURL, invalidURL) "
-            + "values (1, -1, 22, 2, 33,3, 1, 2, 3.9, 23.2, 33.3, 44,5, 'test string', '1799-05-26',"
-            + "'12:35:45', '2007-10-09 14:28:02.0','1221-09-22 10:11:55', 1, 2, 3, 4,"
-            + "'Test text message tiny', 'Test text', 'Test text message medium',"
-            + "'Test text message long', " + Long.MAX_VALUE + ", " + Long.MIN_VALUE + ","
-            + "null, null);";
-
-    static final String ALL_TYPES_TABLE = "type";
-
-    @Override public void setUp() throws Exception {
-        super.setUp();
-        Support_SQL.loadDriver();
-        db = new Database();
-        db.open(dbFile.getPath(), 0);
-        db.exec(DatabaseCreator.CREATE_TABLE_SIMPLE1, null);
-        DatabaseCreator.fillSimpleTable1(conn);
-
-        st = new Stmt();
-    }
-
-    @Override public void tearDown() throws Exception {
-        if (st != null) {
-            try {
-                st.close();
-            } catch (Exception e) {
-            }
-        }
-        db.close();
-        Connection con = Support_SQL.getConnection();
-        con.close();
-        super.tearDown();
-    }
-
-    public void testStmt() throws Exception {
-        db.prepare("");
-
-        try {
-            st.step();
-            fail("Cannot execute non prepared Stmt");
-        } catch (SQLite.Exception expected) {
-        }
-    }
-
-    public void testPrepare() throws Exception {
-        try {
-            st = db.prepare("");
-            st.prepare();
-            fail("statement is closed");
-        } catch (SQLite.Exception expected) {
-            assertEquals("stmt already closed", expected.getMessage());
-        }
-
-        st = new Stmt();
-        st = db.prepare("select * from " + DatabaseCreator.SIMPLE_TABLE1);
-        assertFalse(st.prepare());
-        st = new Stmt();
-        st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                + " values (:one,:two,:three)");
-        assertFalse(st.prepare());
-        st = new Stmt();
-        st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                + " values (:one,:two,:three)");
-        st.bind(1, 1);
-        st.bind(2, 10);
-        st.bind(3, 30);
-        assertFalse(st.prepare());
-        st = db.prepare("select * from " + DatabaseCreator.SIMPLE_TABLE1
-                + "; " + "delete from " + DatabaseCreator.SIMPLE_TABLE1
-                + " where id = 5; " + "insert into "
-                + DatabaseCreator.SIMPLE_TABLE1 + " values(5, 10, 20); "
-                + "select * from " + DatabaseCreator.SIMPLE_TABLE1 + ";");
-        assertTrue(st.prepare());
-        assertTrue(st.prepare());
-        assertTrue(st.prepare());
-        assertFalse(st.prepare());
-    }
-
-    public void testStep() throws Exception {
-        try {
-            st.step();
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-            assertEquals("stmt already closed", expected.getMessage());
-        }
-
-        st = new Stmt();
-        st = db.prepare("select name from sqlite_master where type = 'table'");
-        st.step();
-    }
-
-    public void testClose() throws Exception {
-        st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                + " values (:one,:two,:three)");
-        st.close();
-
-        try {
-            st.step();
-            fail("Test fails");
-        } catch (SQLite.Exception expected) {
-            assertEquals("stmt already closed", expected.getMessage());
-        }
-    }
-
-    public void testReset() throws Exception {
-        db.exec("create table TEST (res integer not null)", null);
-
-        st = db.prepare("insert into TEST values (:one);");
-        st.bind(1, 1);
-        st.step();
-
-        // verify that parameter is still bound
-        st.reset();
-        assertEquals(1,st.bind_parameter_count());
-        st.step();
-
-        TableResult count = db.get_table("select count(*) from TEST where res=1", null);
-
-        String[] row0 = (String[]) count.rows.elementAt(0);
-        assertEquals(2, Integer.parseInt(row0[0]));
-    }
-
-    public void testClear_bindings() {
-        try {
-            st.clear_bindings();
-        } catch (SQLite.Exception expected) {
-            assertEquals("unsupported", expected.getMessage());
-        }
-    }
-
-    public void testBindIntInt() throws Exception {
-        int input = 0;
-        int maxVal = Integer.MAX_VALUE;
-        int minVal = Integer.MIN_VALUE;
-
-        db.exec("create table TEST (res integer)", null);
-        st = db.prepare("insert into TEST values (:one);");
-        st.bind(1, input);
-        st.step();
-
-        st.reset();
-        st.bind(1,maxVal);
-        st.step();
-
-        st.reset();
-        st.bind(1,minVal);
-        st.step();
-
-        TableResult r = db.get_table("select * from TEST");
-
-        String[] row0 = (String[]) r.rows.elementAt(0);
-        assertEquals(input,Integer.parseInt(row0[0]));
-
-        String[] row1 = (String[]) r.rows.elementAt(1);
-        assertEquals(maxVal,Integer.parseInt(row1[0]));
-
-        String[] row2 = (String[]) r.rows.elementAt(2);
-        assertEquals(minVal,Integer.parseInt(row2[0]));
-
-        try {
-            st.close();
-            st.bind(1,Integer.MIN_VALUE);
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-        }
-    }
-
-    public void testBindIntLong() throws Exception {
-        long input = 0;
-        long maxVal = Long.MAX_VALUE;
-        long minVal = Long.MIN_VALUE;
-
-        db.exec("create table TEST (res long)", null);
-        st = db.prepare("insert into TEST values (:one);");
-        st.bind(1, input);
-        st.step();
-
-        st.reset();
-        st.bind(1,maxVal);
-        st.step();
-
-        st.reset();
-        st.bind(1,minVal);
-        st.step();
-
-        TableResult r = db.get_table("select * from TEST");
-
-        String[] row0 = (String[]) r.rows.elementAt(0);
-        assertEquals(input,Long.parseLong(row0[0]));
-
-        String[] row1 = (String[]) r.rows.elementAt(1);
-        assertEquals(maxVal,Long.parseLong(row1[0]));
-
-        String[] row2 = (String[]) r.rows.elementAt(2);
-        assertEquals(minVal,Long.parseLong(row2[0]));
-
-        try {
-            st.close();
-            st.bind(1,Long.MIN_VALUE);
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-        }
-    }
-
-    public void testBindIntDouble() throws Exception {
-        double input = 0.0;
-        double maxVal = Double.MAX_VALUE;
-        double minVal = Double.MIN_VALUE;
-        double negInf = Double.NEGATIVE_INFINITY;
-        double posInf = Double.POSITIVE_INFINITY;
-        double nan = Double.NaN;
-
-        db.exec("create table TEST (res double)", null);
-        st = db.prepare("insert into TEST values (:one);");
-        st.bind(1, input);
-        st.step();
-
-        st.reset();
-        st.bind(1, maxVal);
-        st.step();
-
-        st.reset();
-        st.bind(1, minVal);
-        st.step();
-
-        st.reset();
-        st.bind(1, negInf);
-        st.step();
-
-        st.reset();
-        st.bind(1, posInf);
-        st.step();
-
-        st.reset();
-        st.bind(1, nan);
-        st.step();
-
-
-        TableResult r = db.get_table("select * from TEST");
-
-        String[] row0 = (String[]) r.rows.elementAt(0);
-        assertTrue(Double.compare(input, Double.parseDouble(row0[0])) == 0);
-
-        String[] row1 = (String[]) r.rows.elementAt(1);
-        assertFalse(Double.compare(maxVal, Double.parseDouble(row1[0])) == 0);
-        assertTrue(Double.compare(maxVal, Double.parseDouble(row1[0])) < 0);
-        assertTrue(Double.isInfinite(Double.parseDouble(row1[0])));
-
-        String[] row2 = (String[]) r.rows.elementAt(2);
-        assertTrue(Double.compare(minVal, Double.parseDouble(row2[0])) == 0);
-
-        String[] row3 = (String[]) r.rows.elementAt(3);
-        assertEquals("Double.NEGATIVE_INFINITY SQLite representation",
-                "-Inf", row3[0]);
-
-        String[] row4 = (String[]) r.rows.elementAt(4);
-        assertEquals("Double.POSITIVE_INFINITY SQLite representation",
-                "Inf", row4[0]);
-
-        String[] row5 = (String[]) r.rows.elementAt(4);
-        assertEquals("Double.Nan SQLite representation", "Inf", row5[0]);
-
-        try {
-            st.close();
-            st.bind(1,0.0);
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-        }
-    }
-
-    public void testBindIntByteArray() throws Exception {
-        String name = "Hello World";
-        byte[] b = name.getBytes();
-        String stringInHex = "";
-
-        db.exec(DatabaseCreator.CREATE_TABLE_PARENT, null);
-        st = db.prepare("insert into " + DatabaseCreator.PARENT_TABLE
-                + " values (:one, :two);");
-        st.bind(1, 2);
-        st.bind(2, b);
-        st.step();
-
-        //compare what was stored with input based on Hex representation
-        // since type of column is CHAR
-        TableResult r = db.get_table("select * from "
-                + DatabaseCreator.PARENT_TABLE);
-        String[] row = (String[]) r.rows.elementAt(0);
-
-        for (byte aByte : b) {
-            stringInHex += Integer.toHexString(aByte);
-        }
-        stringInHex = "X'" + stringInHex + "'";
-        assertTrue(stringInHex.equalsIgnoreCase(row[1]));
-
-        try {
-            st.close();
-            st.bind(1,name.getBytes());
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-        }
-    }
-
-    public void testBindIntString() throws Exception {
-        String name = "Hello World";
-        db.exec(DatabaseCreator.CREATE_TABLE_PARENT, null);
-        st = db.prepare("insert into " + DatabaseCreator.PARENT_TABLE
-                + " values (:one, :two);");
-        st.bind(1, 2);
-        st.bind(2, name);
-        st.step();
-
-        TableResult r = db.get_table("select * from "
-                + DatabaseCreator.PARENT_TABLE);
-        String[] row = (String[]) r.rows.elementAt(0);
-        assertEquals(name,row[1]);
-
-        try {
-            st.close();
-            st.bind(1,name);
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-        }
-    }
-
-    public void testBindInt() throws Exception {
-        try {
-            st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                    + " values (:one,:two,:three)");
-            st.bind(4);
-            st.bind(1, 4);
-            st.bind(2, 10);
-            st.bind(3, 30);
-            st.step();
-            fail();
-        } catch (SQLite.Exception expected) {
-            // What happens if null is bound to non existing variable position
-            assertEquals("parameter position out of bounds", expected.getMessage());
-        }
-
-        // functional tests
-
-        try {
-            st.reset();
-            st.bind(1);
-            st.bind(2, 10);
-            st.bind(3, 30);
-            st.step();
-            fail();
-        } catch (SQLite.Exception expected) {
-            // What happens if null is bound to NON NULL field
-            assertEquals("SQL logic error or missing database", expected.getMessage());
-        }
-
-        st.reset();
-        st.bind(1, 3);
-        st.bind(2);
-        st.bind(3, 30);
-        st.step();
-    }
-
-    public void testBind_zeroblob() {
-        try {
-            st.bind_zeroblob(1, 128);
-            fail();
-        } catch (SQLite.Exception expected) {
-            assertEquals("unsupported", expected.getMessage());
-        }
-    }
-
-    public void testBind_parameter_count() throws Exception {
-        try {
-            st.bind_parameter_count();
-            fail();
-        } catch (SQLite.Exception expected) {
-            assertEquals("stmt already closed", expected.getMessage());
-        }
-
-        st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                + " values (:one,:two,:three)");
-        assertEquals(3, st.bind_parameter_count());
-
-        st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                + " values (?, ?, ?)");
-        assertEquals(3, st.bind_parameter_count());
-
-        st = db.prepare("select * from " + DatabaseCreator.SIMPLE_TABLE1);
-        assertEquals(0, st.bind_parameter_count());
-
-        try {
-            st.close();
-            st.bind_parameter_count();
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-        }
-
-    }
-
-    public void testBind_parameter_name() {
-        try {
-            st.bind_parameter_name(1);
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-            assertEquals("stmt already closed", expected.getMessage());
-        }
-
-        try {
-            st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                    + " values (:one,:two,:three)");
-            assertEquals(":one", st.bind_parameter_name(1));
-            assertEquals(":two", st.bind_parameter_name(2));
-            assertEquals(":three", st.bind_parameter_name(3));
-            st.bind_parameter_name(4);
-            fail();
-        } catch (SQLite.Exception expected) {
-            assertEquals("parameter position out of bounds", expected.getMessage());
-        }
-    }
-
-    public void testBind_parameter_index() throws Exception {
-        try {
-            st.bind_parameter_index("");
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-            assertEquals("stmt already closed", expected.getMessage());
-        }
-
-        st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                + " values (:one,:two,:three)");
-        assertEquals(3, st.bind_parameter_index(":three"));
-
-        st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                + " values (:one,:two,:three)");
-        assertEquals(0, st.bind_parameter_index(":t"));
-
-        st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                + " values (?, ?, ?)");
-        assertEquals(0, st.bind_parameter_index("?"));
-    }
-
-    public void testColumn_int() throws Exception {
-        db.exec(CREATE_ALL_TYPES, null);
-        db.exec(INSERT_ALL_TYPES, null);
-
-        Object columnObject;
-        int intColumn;
-        String selectStmt = "select * from "+DatabaseCreator.SIMPLE_TABLE1;
-
-        st = db.prepare(selectStmt);
-        st.step();
-        // select 'speed' value
-        columnObject = st.column(1);
-        intColumn = st.column_int(1);
-        assertNotNull(intColumn);
-
-        assertTrue("Integer".equalsIgnoreCase(st.column_decltype(1)));
-        int stSpeed = Integer.parseInt(columnObject.toString());
-        assertNotNull(stSpeed);
-        assertEquals( intColumn, stSpeed);
-        assertEquals(10,stSpeed);
-
-        selectStmt = "select TextVal from "+ ALL_TYPES_TABLE;
-
-        st = db.prepare(selectStmt);
-        st.step();
-        st.column_int(0);
-    }
-
-    public void testColumn_long() throws Exception {
-        Object columnObject;
-        long longColumn;
-        String selectStmt = "select * from "+DatabaseCreator.SIMPLE_TABLE1;
-        st = db.prepare(selectStmt);
-        st.step();
-        columnObject = st.column(1);
-        longColumn = st.column_long(1);
-        assertNotNull(longColumn);
-        // column declared as integer
-        assertTrue("Integer".equalsIgnoreCase(st.column_decltype(1)));
-        int stSpeed = Integer.parseInt(columnObject.toString());
-        assertNotNull(stSpeed);
-        assertEquals( longColumn, stSpeed);
-
-        try {
-            st.column_long(4);
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-            assertEquals("column out of bounds", expected.getMessage());
-        }
-
-        try {
-            st.column_long(-1);
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-            assertEquals("column out of bounds", expected.getMessage());
-        }
-    }
-
-    public void testColumn_double() throws Exception {
-        db.exec(CREATE_ALL_TYPES, null);
-        db.exec(INSERT_ALL_TYPES, null);
-
-        double doubleColumn;
-        double actualVal = 23.2;
-        String selectStmt = "select DoubleVal from "+ ALL_TYPES_TABLE;
-
-        st = db.prepare(selectStmt);
-        st.step();
-        // select double value
-        doubleColumn = st.column_double(0);
-        assertNotNull(doubleColumn);
-
-        assertTrue("DOUBLE".equalsIgnoreCase(st.column_decltype(0)));
-        assertNotNull(doubleColumn);
-        assertEquals( actualVal, doubleColumn);
-
-        // Exception test
-        selectStmt = "select dateVal from "+ ALL_TYPES_TABLE;
-
-        st = db.prepare(selectStmt);
-        st.step();
-        // select double value
-        st.column_double(0);
-    }
-
-    public void testColumn_bytes() throws Exception {
-        db.exec("create table B(id integer primary key, val blob)",null);
-        db.exec("insert into B values(1, zeroblob(128))", null);
-        st = db.prepare("select val from B where id = 1");
-        assertTrue(st.step());
-        st.column_bytes(0);
-    }
-
-    public void testColumn_string() throws Exception {
-        db.exec(CREATE_ALL_TYPES, null);
-        db.exec(INSERT_ALL_TYPES, null);
-
-        String stringColumn;
-        String actualVal = "test string";
-        String selectStmt = "select charStr from "+ ALL_TYPES_TABLE;
-
-        st = db.prepare(selectStmt);
-        st.step();
-        // select string value
-        stringColumn = st.column_string(0);
-        assertNotNull(stringColumn);
-
-        assertTrue("CHAR(20)".equalsIgnoreCase(st.column_decltype(0)));
-        assertNotNull(stringColumn);
-        assertEquals( actualVal, stringColumn);
-
-        // Exception test
-        selectStmt = "select DoubleVal from "+ ALL_TYPES_TABLE;
-
-        st = db.prepare(selectStmt);
-        st.step();
-        st.column_string(0);
-    }
-
-    public void testColumn_type() throws Exception {
-        db.exec(CREATE_ALL_TYPES, null);
-        db.exec(INSERT_ALL_TYPES, null);
-        st = db.prepare("select * from " + ALL_TYPES_TABLE);
-        st.step();
-
-        // Exception test
-        try {
-            st.column_type(100);
-            fail();
-        } catch (SQLite.Exception expected) {
-        }
-
-        /*
-        Dictionary
-
-        public static final int SQLITE_INTEGER = 1;
-        public static final int SQLITE_FLOAT = 2;
-        public static final int SQLITE_BLOB = 4;
-        public static final int SQLITE_NULL = 5;
-        public static final int SQLITE3_TEXT = 3;
-        public static final int SQLITE_NUMERIC = -1;
-        */
-
-        assertEquals(Constants.SQLITE3_TEXT, st.column_type(23)); // ok TEXT
-        assertEquals(Constants.SQLITE3_TEXT, st.column_type(13)); // CHAR(20)
-
-        assertEquals(Constants.SQLITE_FLOAT, st.column_type(8));
-        assertEquals(Constants.SQLITE_FLOAT, st.column_type(9));
-        assertEquals(Constants.SQLITE_FLOAT, st.column_type(10)); // FLOAT
-
-        for (int i = 0; i < 8; i++) {
-            assertEquals("Expected Integer at position " + i,
-                    Constants.SQLITE_INTEGER, st.column_type(i));
-        }
-
-        assertEquals(Constants.SQLITE_NULL, st.column_type(28));
-        assertEquals(Constants.SQLITE_NULL, st.column_type(29));
-
-        // Failing tests
-        assertTrue("INTEGER".equalsIgnoreCase(st.column_decltype(12)));
-        assertEquals(Constants.SQLITE_INTEGER, st.column_type(12));
-
-        assertTrue("FLOAT".equalsIgnoreCase(st.column_decltype(11)));
-        assertEquals(Constants.SQLITE_FLOAT, st.column_type(11)); // FLOAT ->
-                                                                  // got INTEGER
-        assertTrue("BLOB".equalsIgnoreCase(st.column_decltype(19)));
-        assertEquals(Constants.SQLITE_BLOB, st.column_type(19)); // Blob got
-                                                                 // INTEGER
-
-    }
-
-    /**
-     * Wrong value is returned in case of a prepared statement to which a '*' bound
-     */
-    public void testColumn_count() throws Exception {
-        String selectStmt = "select * from "+DatabaseCreator.SIMPLE_TABLE1;
-        st = db.prepare(selectStmt);
-
-        assertEquals(3, st.column_count());
-
-        st.step();
-        int columnCount = st.column_count();
-        assertNotNull(columnCount);
-        assertEquals( 3, columnCount);
-
-        // actual prepared statement
-        selectStmt = "select ? from "+DatabaseCreator.SIMPLE_TABLE1;
-        st = db.prepare(selectStmt);
-
-        assertEquals(3, st.column_count());
-
-        st.bind(1, "*");
-        st.step();
-        columnCount = st.column_count();
-        assertNotNull(columnCount);
-        assertEquals( 3, columnCount);
-    }
-
-    public void testColumn() throws Exception {
-        Object columnObject;
-        int intColumn;
-        String selectStmt = "select * from "+DatabaseCreator.SIMPLE_TABLE1;
-        db.get_table(selectStmt);
-        st = db.prepare(selectStmt);
-        st.step();
-        columnObject = st.column(1);
-        intColumn = st.column_int(1);
-        assertNotNull(intColumn);
-        assertTrue("Integer".equalsIgnoreCase(st.column_decltype(1)));
-        int stSpeed = Integer.parseInt(columnObject.toString());
-        assertNotNull(stSpeed);
-        assertEquals( intColumn, stSpeed);
-
-        try {
-            assertNotNull(columnObject);
-            ((Integer) columnObject).intValue();
-            fail("Cast to Integer should fail");
-        } catch (ClassCastException expected) {
-        }
-
-        try {
-            st.column(4);
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-            assertEquals("column out of bounds", expected.getMessage());
-        }
-
-        try {
-            st.column(-1);
-            fail("Exception expected");
-        } catch (SQLite.Exception expected) {
-            assertEquals("column out of bounds", expected.getMessage());
-        }
-    }
-
-    public void testColumn_table_name() {
-        try {
-            st = db.prepare("select * from " + DatabaseCreator.SIMPLE_TABLE1);
-            st.column_table_name(1);
-            fail("Function is now supported.");
-        } catch (SQLite.Exception expected) {
-            assertEquals("unsupported", expected.getMessage());
-        }
-    }
-
-    public void testColumn_database_name() {
-        try {
-            st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
-                    + " values (:one,:two,:three)");
-            st.column_database_name(1);
-            fail("Function is now supported.");
-        } catch (SQLite.Exception expected) {
-            assertEquals("unsupported", expected.getMessage());
-        }
-    }
-
-    public void testColumn_decltype() throws Exception {
-        db.exec(CREATE_ALL_TYPES, null);
-        db.exec(INSERT_ALL_TYPES, null);
-        st = db.prepare("select * from " + ALL_TYPES_TABLE);
-        st.step();
-
-        // Exception test
-        try {
-            st.column_decltype(100);
-            fail();
-        } catch (SQLite.Exception expected) {
-        }
-
-        assertTrue(st.column_decltype(0), "BOOLEAN".equalsIgnoreCase(st
-                .column_decltype(0)));
-        assertTrue(st.column_decltype(1), "INT".equalsIgnoreCase(st
-                .column_decltype(1)));
-        assertTrue(st.column_decltype(2), "LONG".equalsIgnoreCase(st
-                .column_decltype(2)));
-        assertTrue(st.column_decltype(3), "BIGINT".equalsIgnoreCase(st
-                .column_decltype(3)));
-        assertTrue(st.column_decltype(4), "TINYINT".equalsIgnoreCase(st
-                .column_decltype(4)));
-        assertTrue(st.column_decltype(5), "SMALLINT".equalsIgnoreCase(st
-                .column_decltype(5)));
-        assertTrue(st.column_decltype(6), "MEDIUMINT".equalsIgnoreCase(st
-                .column_decltype(6)));
-        assertTrue(st.column_decltype(7), "INTEGER".equalsIgnoreCase(st
-                .column_decltype(7)));
-        assertTrue(st.column_decltype(8), "REAL".equalsIgnoreCase(st
-                .column_decltype(8)));
-        assertTrue(st.column_decltype(9), "DOUBLE".equalsIgnoreCase(st
-                .column_decltype(9)));
-        assertTrue(st.column_decltype(10), "FLOAT".equalsIgnoreCase(st
-                .column_decltype(10)));
-        assertTrue(st.column_decltype(11), "DECIMAL".equalsIgnoreCase(st
-                .column_decltype(11)));
-        assertTrue(st.column_decltype(12), "NUMERIC".equalsIgnoreCase(st
-                .column_decltype(12)));
-        assertTrue(st.column_decltype(13), "CHAR(20)".equalsIgnoreCase(st
-                .column_decltype(13)));
-
-        assertTrue(st.column_decltype(19), "BLOB".equalsIgnoreCase(st
-                .column_decltype(19)));
-
-        assertTrue(st.column_decltype(23), "TEXT".equalsIgnoreCase(st
-                .column_decltype(23)));
-        assertTrue(st.column_decltype(28), "URL".equalsIgnoreCase(st
-                .column_decltype(28)));
-        assertTrue(st.column_decltype(29), "URL".equalsIgnoreCase(st
-                .column_decltype(29)));
-    }
-
-    public void testColumn_origin_name() {
-        try {
-            st = db.prepare("select * from " + DatabaseCreator.SIMPLE_TABLE1);
-            st.column_origin_name(1);
-            fail("Function is now supported.");
-        } catch (SQLite.Exception expected) {
-            assertEquals("unsupported", expected.getMessage());
-        }
-    }
-}
diff --git a/luni/src/test/java/libcore/sqlite/QueryTimeoutTest.java b/luni/src/test/java/libcore/sqlite/QueryTimeoutTest.java
deleted file mode 100644
index 8febfff..0000000
--- a/luni/src/test/java/libcore/sqlite/QueryTimeoutTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package libcore.sqlite;
-
-import SQLite.Database;
-import SQLite.Function;
-import SQLite.FunctionContext;
-import SQLite.JDBC2z.JDBCConnection;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import junit.framework.TestCase;
-import tests.support.Support_SQL;
-
-
-/**
- * Test that statements honor their timeout.
- */
-public final class QueryTimeoutTest extends TestCase {
-
-    private static final String EXEC_QUERY
-            = "insert into t_copy select a from t_orig where DELAY(2,1)=1";
-
-    private static final String FETCH_QUERY = "select a from t_orig where DELAY(2,1)=1";
-
-    private Connection connection;
-
-    @Override public void setUp() throws Exception {
-        Support_SQL.loadDriver();
-        connection = Support_SQL.getConnection();
-
-        exec("drop table if exists t_orig;");
-        exec("drop table if exists t_copy;");
-        exec("create table t_orig (a int)");
-        exec("create table t_copy (a int)");
-
-        for (int i = 0; i < 7; i++) {
-            exec("insert into t_orig values (" + i + ");");
-        }
-
-        Database database = ((JDBCConnection) connection).getSQLiteDatabase();
-        database.create_function("DELAY", 2, new Function() {
-            @Override public void function(FunctionContext functionContext, String[] args) {
-                try {
-                    int seconds = Integer.parseInt(args[0]);
-                    Thread.sleep(seconds * 1000);
-                } catch (InterruptedException ignored) {
-                }
-                functionContext.set_result(Integer.parseInt(args[1]));
-            }
-            @Override public void last_step(FunctionContext functionContext) {
-            }
-            @Override public void step(FunctionContext functionContext, String[] args) {
-            }
-        });
-
-        connection.setAutoCommit(true);
-    }
-
-    @Override public void tearDown() throws Exception {
-        connection.close();
-    }
-
-    private void exec(String queryString) throws Exception {
-        System.out.println("Executing " + queryString);
-        Statement statement = null;
-        try {
-            statement = connection.createStatement();
-            statement.execute(queryString);
-        } finally {
-            if (statement != null) {
-                statement.close();
-            }
-        }
-    }
-
-    public void testPreparedStatementFetch() throws Exception {
-        PreparedStatement statement = connection.prepareStatement(FETCH_QUERY);
-        statement.setQueryTimeout(1);
-        ResultSet resultSet = null;
-        try {
-            resultSet = statement.executeQuery();
-            while (resultSet.next()) {
-            }
-            fail();
-        } catch (SQLException expected) {
-        } finally {
-            statement.close();
-            if (resultSet != null) {
-                resultSet.close();
-            }
-        }
-    }
-
-    public void testPreparedStatementUpdate() throws Exception {
-        PreparedStatement statement = connection.prepareStatement(EXEC_QUERY);
-        try {
-            statement.setQueryTimeout(1);
-            statement.execute();
-            fail();
-        } catch (SQLException expected) {
-        } finally {
-            statement.close();
-        }
-    }
-
-    public void testInvalidTimeout() throws Exception {
-        connection.setAutoCommit(true);
-        PreparedStatement statement = connection.prepareStatement("select 'hello'");
-
-        try {
-            statement.setQueryTimeout(-1);
-            fail();
-        } catch (SQLException expected) {
-        }
-
-        ResultSet resultSet = statement.executeQuery();
-        resultSet.close();
-        statement.close();
-    }
-
-    public void testExecuteUpdate() throws Exception {
-        Statement statement = connection.createStatement();
-        try {
-            statement.setQueryTimeout(1);
-            statement.executeUpdate(EXEC_QUERY);
-            fail();
-        } catch (SQLException expected) {
-        } finally {
-            statement.close();
-        }
-    }
-
-    public void testTimeoutAndStatementReuse() throws Exception {
-        Statement statement = connection.createStatement();
-        statement.setQueryTimeout(1);
-        for (int i = 0; i < 3; i++) {
-            try {
-                ResultSet resultSet = statement.executeQuery(FETCH_QUERY);
-                while (resultSet.next()) {
-                }
-                fail();
-            } catch (SQLException expected) {
-            }
-        }
-        statement.close();
-    }
-}
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
index 7886e3e..ad084e1 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
@@ -68,7 +68,17 @@
      * java.security.Signature#clone()
      */
     public void test_clone() throws Exception {
+        // A Signature may be cloneable according to the API, in practice the implementation isn't
+        // once it has been initialized. Checking for runtime exceptions rather than useful
+        // behavior.
         Signature s = Signature.getInstance("DSA");
+        Signature clone = (Signature) s.clone();
+        assertNotNull(clone);
+        assertEquals(s.getAlgorithm(), clone.getAlgorithm());
+        assertEquals(s.getProvider(), clone.getProvider());
+
+        KeyPair keyPair = getDsaKeys();
+        s.initSign(keyPair.getPrivate());
         try {
             s.clone();
             fail();