am 008b2de6: Add additional field checks for deserialization.

* commit '008b2de6760bc98b9651bb0e97e45ea76c22f65b':
  Add additional field checks for deserialization.
diff --git a/Android.mk b/Android.mk
index a0599cf..2e9b76e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -61,9 +61,12 @@
         dalvik \
         $(HOST_OUT)/bin/dalvikvm \
         $(HOST_OUT)/bin/dexopt \
+        $(HOST_OUT)/lib/libconscrypt_jni.so \
         $(HOST_OUT)/lib/libjavacore.so \
         cacerts-host \
         core-hostdex \
+        conscrypt-hostdex \
+        okhttp-hostdex \
         bouncycastle-hostdex \
         apache-xml-hostdex \
         apache-harmony-tests-hostdex \
diff --git a/Docs.mk b/Docs.mk
index 875a008..48cfd03 100644
--- a/Docs.mk
+++ b/Docs.mk
@@ -21,6 +21,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 \
    luni/src/main/java/java \
    luni/src/main/java/javax \
    luni/src/main/java/org/xml/sax \
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 98de1f2..673c0bf 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -50,7 +50,8 @@
 endef
 
 # The Java files and their associated resources.
-core_src_files := $(call all-main-java-files-under,dalvik dom json luni support xml)
+core_src_files := $(call all-main-java-files-under,dalvik dex dom json luni support xml)
+core_src_files += $(call all-main-java-files-under,libdvm)
 core_resource_dirs := $(call all-core-resource-dirs,main)
 test_resource_dirs := $(call all-core-resource-dirs,test)
 
@@ -90,15 +91,40 @@
 core-intermediates := ${intermediates}
 
 
-# Make the core-tests library.
-ifeq ($(LIBCORE_SKIP_TESTS),)
+# Create the conscrypt library
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-test-java-files-under,dalvik dom json luni support xml)
+LOCAL_SRC_FILES := $(call all-main-java-files-under,crypto)
+LOCAL_JAVA_LIBRARIES := core
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JARJAR_RULES := $(LOCAL_PATH)/crypto/jarjar-rules.txt
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := conscrypt
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+include $(BUILD_JAVA_LIBRARY)
+
+# Create the conscrypt library without jarjar for tests
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-main-java-files-under,crypto)
+LOCAL_JAVA_LIBRARIES := core
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := conscrypt-nojarjar
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+include $(BUILD_JAVA_LIBRARY)
+
+
+ifeq ($(LIBCORE_SKIP_TESTS),)
+# Make the core-tests library.
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-test-java-files-under,crypto dalvik dom harmony-tests json luni support xml)
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit
-LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc mockwebserver nist-pkix-tests
+LOCAL_JAVA_LIBRARIES := bouncycastle core conscrypt-nojarjar core-junit okhttp
+LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc mockwebserver nist-pkix-tests okhttp-tests
 LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JARJAR_RULES := $(LOCAL_PATH)/crypto/jarjar-rules.txt
 LOCAL_MODULE := core-tests
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
 include $(BUILD_STATIC_JAVA_LIBRARY)
@@ -123,6 +149,12 @@
 # Build for the host.
 #
 
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-main-java-files-under, dex)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := dex-host
+include $(BUILD_HOST_JAVA_LIBRARY)
+
 ifeq ($(WITH_HOST_DALVIK),true)
 
     # Definitions to make the core library.
@@ -145,15 +177,41 @@
 
     include $(BUILD_HOST_JAVA_LIBRARY)
 
+    # Make the conscrypt-hostdex library
+    include $(CLEAR_VARS)
+    LOCAL_SRC_FILES := $(call all-main-java-files-under,crypto)
+    LOCAL_JAVA_LIBRARIES := core-hostdex
+    LOCAL_NO_STANDARD_LIBRARIES := true
+    LOCAL_JAVACFLAGS := $(local_javac_flags)
+    LOCAL_JARJAR_RULES := $(LOCAL_PATH)/crypto/jarjar-rules.txt
+    LOCAL_BUILD_HOST_DEX := true
+    LOCAL_MODULE_TAGS := optional
+    LOCAL_MODULE := conscrypt-hostdex
+    LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+    include $(BUILD_HOST_JAVA_LIBRARY)
+
+    # Make the conscrypt-hostdex-nojarjar for tests
+    include $(CLEAR_VARS)
+    LOCAL_SRC_FILES := $(call all-main-java-files-under,crypto)
+    LOCAL_JAVA_LIBRARIES := core-hostdex
+    LOCAL_NO_STANDARD_LIBRARIES := true
+    LOCAL_JAVACFLAGS := $(local_javac_flags)
+    LOCAL_BUILD_HOST_DEX := true
+    LOCAL_MODULE_TAGS := optional
+    LOCAL_MODULE := conscrypt-hostdex-nojarjar
+    LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+    include $(BUILD_HOST_JAVA_LIBRARY)
+
     # Make the core-tests library.
     ifeq ($(LIBCORE_SKIP_TESTS),)
     include $(CLEAR_VARS)
-    LOCAL_SRC_FILES := $(call all-test-java-files-under,dalvik dom json luni support xml)
+    LOCAL_SRC_FILES := $(call all-test-java-files-under,crypto dalvik dom json luni support xml)
     LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
     LOCAL_NO_STANDARD_LIBRARIES := true
-    LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-hostdex core-junit-hostdex
+    LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-hostdex conscrypt-hostdex-nojarjar core-junit-hostdex okhttp-hostdex
     LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host
     LOCAL_JAVACFLAGS := $(local_javac_flags)
+    LOCAL_JARJAR_RULES := $(LOCAL_PATH)/crypto/jarjar-rules.txt
     LOCAL_MODULE_TAGS := optional
     LOCAL_MODULE := core-tests-hostdex
     LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
diff --git a/NativeCode.mk b/NativeCode.mk
index b7c8b0e..3a22575 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -52,29 +52,6 @@
 # sub.mk files don't see anything stray from the last rule that was
 # set up.
 
-# Set up the test library first
-ifeq ($(LIBCORE_SKIP_TESTS),)
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(core_magic_local_target)
-core_src_files :=
-
-# Include the sub.mk files.
-$(foreach dir, \
-    luni/src/test/native, \
-    $(eval $(call include-core-native-dir,$(dir))))
-
-# This is for the test library, so rename the variable.
-test_src_files := $(core_src_files)
-core_src_files :=
-
-# Extract out the allowed LOCAL_* variables. Note: $(sort) also
-# removes duplicates.
-test_c_includes := $(sort libcore/include $(LOCAL_C_INCLUDES) $(JNI_H_INCLUDE))
-test_shared_libraries := $(sort $(LOCAL_SHARED_LIBRARIES))
-test_static_libraries := $(sort $(LOCAL_STATIC_LIBRARIES))
-endif # LIBCORE_SKIP_TESTS
-
-
 include $(CLEAR_VARS)
 LOCAL_MODULE := $(core_magic_local_target)
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
@@ -82,67 +59,52 @@
 
 # Include the sub.mk files.
 $(foreach dir, \
-    dalvik/src/main/native luni/src/main/native, \
+    crypto/src/main/native dalvik/src/main/native luni/src/main/native, \
     $(eval $(call include-core-native-dir,$(dir))))
 
-# Extract out the allowed LOCAL_* variables. Note: $(sort) also
-# removes duplicates.
-core_c_includes := $(sort libcore/include $(LOCAL_C_INCLUDES) $(JNI_H_INCLUDE))
-core_shared_libraries := $(sort $(LOCAL_SHARED_LIBRARIES))
-core_static_libraries := $(sort $(LOCAL_STATIC_LIBRARIES))
+# Extract out the allowed LOCAL_* variables.
+core_c_includes := libcore/include $(LOCAL_C_INCLUDES)
+core_shared_libraries := $(LOCAL_SHARED_LIBRARIES)
+core_static_libraries := $(LOCAL_STATIC_LIBRARIES)
+core_cflags := -Wall -Wextra -Werror
+core_cflags += -DJNI_JARJAR_PREFIX="com/android/"
 
+core_test_files := \
+  luni/src/test/native/test_openssl_engine.cpp \
 
 #
 # Build for the target (device).
 #
 
 include $(CLEAR_VARS)
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
 LOCAL_CFLAGS += $(core_cflags)
 LOCAL_CPPFLAGS += $(core_cppflags)
-ifeq ($(TARGET_ARCH),arm)
-# Ignore "note: the mangling of 'va_list' has changed in GCC 4.4"
-LOCAL_CFLAGS += -Wno-psabi
-endif
-
-# Define the rules.
-LOCAL_SRC_FILES := $(core_src_files)
-LOCAL_C_INCLUDES := $(core_c_includes)
-LOCAL_SHARED_LIBRARIES := $(core_shared_libraries) libexpat libicuuc libicui18n libssl libcrypto libz libnativehelper
-LOCAL_STATIC_LIBRARIES := $(core_static_libraries)
+LOCAL_SRC_FILES += $(core_src_files)
+LOCAL_C_INCLUDES += $(core_c_includes)
+LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat libicuuc libicui18n libssl libcrypto libz libnativehelper
+LOCAL_STATIC_LIBRARIES += $(core_static_libraries)
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := libjavacore
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
-
-LOCAL_C_INCLUDES += external/stlport/stlport bionic/ bionic/libstdc++/include
-LOCAL_SHARED_LIBRARIES += libstlport
-
+include external/stlport/libstlport.mk
 include $(BUILD_SHARED_LIBRARY)
 
 
-# Test library
+# Test JNI library.
 ifeq ($(LIBCORE_SKIP_TESTS),)
-include $(CLEAR_VARS)
 
-LOCAL_CFLAGS += -Wall -Wextra -Werror
+include $(CLEAR_VARS)
 LOCAL_CFLAGS += $(core_cflags)
 LOCAL_CPPFLAGS += $(core_cppflags)
-ifeq ($(TARGET_ARCH),arm)
-# Ignore "note: the mangling of 'va_list' has changed in GCC 4.4"
-LOCAL_CFLAGS += -Wno-psabi
-endif
-
-# Define the rules.
-LOCAL_SRC_FILES := $(test_src_files)
-LOCAL_C_INCLUDES := $(test_c_includes)
-LOCAL_SHARED_LIBRARIES := $(test_shared_libraries)
-LOCAL_STATIC_LIBRARIES := $(test_static_libraries)
+LOCAL_SRC_FILES += $(core_test_files)
+LOCAL_C_INCLUDES += libcore/include external/openssl/include
+LOCAL_SHARED_LIBRARIES += libcrypto
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE := libjavacoretests
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
-
+include external/stlport/libstlport.mk
 include $(BUILD_SHARED_LIBRARY)
+
 endif # LIBCORE_SKIP_TESTS
 
 
@@ -152,32 +114,44 @@
 
 ifeq ($(WITH_HOST_DALVIK),true)
     include $(CLEAR_VARS)
-    # Define the rules.
-    LOCAL_SRC_FILES := $(core_src_files)
+    LOCAL_SRC_FILES += $(core_src_files)
     LOCAL_CFLAGS += $(core_cflags)
-    LOCAL_C_INCLUDES := $(core_c_includes)
+    LOCAL_C_INCLUDES += $(core_c_includes)
     LOCAL_CPPFLAGS += $(core_cppflags)
-    LOCAL_LDLIBS += -ldl -lpthread
+    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 libicuuc libicui18n libssl libcrypto libz-host
-    LOCAL_STATIC_LIBRARIES := $(core_static_libraries)
+    LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat-host libicuuc-host libicui18n-host libssl-host libcrypto-host libz-host
+    LOCAL_STATIC_LIBRARIES += $(core_static_libraries)
+    include $(BUILD_HOST_SHARED_LIBRARY)
+
+    # Conscrypt native library for nojarjar'd version
+    include $(CLEAR_VARS)
+    LOCAL_SRC_FILES += \
+            crypto/src/main/native/org_conscrypt_NativeCrypto.cpp \
+            luni/src/main/native/AsynchronousSocketCloseMonitor.cpp
+    LOCAL_C_INCLUDES += $(core_c_includes)
+    LOCAL_CPPFLAGS += $(core_cppflags)
+    LOCAL_LDLIBS += -lpthread
+    LOCAL_MODULE_TAGS := optional
+    LOCAL_MODULE := libconscrypt_jni
+    LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
+    LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libssl-host libcrypto-host
+    LOCAL_STATIC_LIBRARIES += $(core_static_libraries)
     include $(BUILD_HOST_SHARED_LIBRARY)
 
     ifeq ($(LIBCORE_SKIP_TESTS),)
     include $(CLEAR_VARS)
-    # Define the rules.
-    LOCAL_SRC_FILES := $(test_src_files)
+    LOCAL_SRC_FILES += $(core_test_files)
     LOCAL_CFLAGS += $(core_cflags)
-    LOCAL_C_INCLUDES := $(test_c_includes)
+    LOCAL_C_INCLUDES += libcore/include external/openssl/include
     LOCAL_CPPFLAGS += $(core_cppflags)
     LOCAL_LDLIBS += -ldl -lpthread
     LOCAL_MODULE_TAGS := optional
     LOCAL_MODULE := libjavacoretests
     LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
-    LOCAL_SHARED_LIBRARIES := $(test_shared_libraries)
-    LOCAL_STATIC_LIBRARIES := $(test_static_libraries)
+    LOCAL_SHARED_LIBRARIES := libcrypto-host
     include $(BUILD_HOST_SHARED_LIBRARY)
     endif # LIBCORE_SKIP_TESTS
 endif
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index ea4e91b..6902006 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -13,6 +13,7 @@
 
 LOCAL_JAVA_LIBRARIES := \
 	bouncycastle \
+	conscrypt \
 	core
 
 LOCAL_MODULE_TAGS := tests
diff --git a/benchmarks/src/benchmarks/regression/SignatureBenchmark.java b/benchmarks/src/benchmarks/regression/SignatureBenchmark.java
index 383dcfd..373b876 100644
--- a/benchmarks/src/benchmarks/regression/SignatureBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/SignatureBenchmark.java
@@ -16,6 +16,7 @@
 
 package benchmarks.regression;
 
+import com.android.org.conscrypt.OpenSSLSignature;
 import com.google.caliper.Param;
 import com.google.caliper.SimpleBenchmark;
 import java.security.KeyPair;
@@ -25,7 +26,6 @@
 import java.security.Signature;
 import java.util.HashMap;
 import java.util.Map;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLSignature;
 
 /**
  * Tests RSA and DSA signature creation and verification.
diff --git a/benchmarks/src/benchmarks/regression/URLConnectionBenchmark.java b/benchmarks/src/benchmarks/regression/URLConnectionBenchmark.java
index 36c5666..a4817b5 100644
--- a/benchmarks/src/benchmarks/regression/URLConnectionBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/URLConnectionBenchmark.java
@@ -18,8 +18,10 @@
 
 import com.google.caliper.Param;
 import com.google.caliper.SimpleBenchmark;
+import com.google.mockwebserver.Dispatcher;
 import com.google.mockwebserver.MockResponse;
 import com.google.mockwebserver.MockWebServer;
+import com.google.mockwebserver.RecordedRequest;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.HttpURLConnection;
@@ -38,6 +40,16 @@
     private MockWebServer server;
     private URL url;
 
+    private static class SingleResponseDispatcher extends Dispatcher {
+        private MockResponse response;
+        SingleResponseDispatcher(MockResponse response) {
+            this.response = response;
+        }
+        @Override public MockResponse dispatch(RecordedRequest request) {
+            return response;
+        }
+    };
+
     protected void setUp() throws Exception {
         readBuffer = new byte[readBufferSize];
         server = new MockWebServer();
@@ -45,10 +57,9 @@
         MockResponse response = new MockResponse();
         responseHeaders.apply(response);
         transferEncoding.setBody(response, bodySize, chunkSize);
-        server.enqueue(response);
 
         // keep serving the same response for all iterations
-        server.setSingleResponse(true);
+        server.setDispatcher(new SingleResponseDispatcher(response));
         server.play();
 
         url = server.getUrl("/");
@@ -56,14 +67,6 @@
     }
 
     protected void tearDown() throws Exception {
-        /*
-         * Entice the server to shut itself down gracefully. The shutdown method
-         * doesn't work on Dalvik because socket.close() doesn't release blocked
-         * threads. Instead, read the last continuously-served request, and then
-         * cause the server to close the otherwise-reusable HTTP connection.
-         */
-        server.setSingleResponse(false);
-        get();
         server.shutdown();
     }
 
diff --git a/crypto/jarjar-rules.txt b/crypto/jarjar-rules.txt
new file mode 100644
index 0000000..0eb6ac2
--- /dev/null
+++ b/crypto/jarjar-rules.txt
@@ -0,0 +1 @@
+rule org.conscrypt.** com.android.@0
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java b/crypto/src/main/java/org/conscrypt/AbstractSessionContext.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
rename to crypto/src/main/java/org/conscrypt/AbstractSessionContext.java
index 0d9b4fb..4aed70c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
+++ b/crypto/src/main/java/org/conscrypt/AbstractSessionContext.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -23,6 +23,7 @@
 import java.io.IOException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.Iterator;
@@ -31,7 +32,6 @@
 import java.util.NoSuchElementException;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLSessionContext;
-import org.apache.harmony.security.provider.cert.X509CertImpl;
 
 /**
  * Supports SSL session caches.
@@ -82,7 +82,7 @@
         }
     }
 
-    public final Enumeration getIds() {
+    public final Enumeration<byte[]> getIds() {
         final Iterator<SSLSession> i = sessionIterator();
         return new Enumeration<byte[]>() {
             private SSLSession next;
@@ -243,12 +243,12 @@
             dais.readFully(sessionData);
 
             int count = dais.readInt();
-            X509CertImpl[] certs = new X509CertImpl[count];
+            X509Certificate[] certs = new X509Certificate[count];
             for (int i = 0; i < count; i++) {
                 length = dais.readInt();
                 byte[] certData = new byte[length];
                 dais.readFully(certData);
-                certs[i] = new X509CertImpl(certData);
+                certs[i] = OpenSSLX509Certificate.fromX509Der(certData);
             }
 
             return new OpenSSLSessionImpl(sessionData, host, port, certs, this);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertException.java b/crypto/src/main/java/org/conscrypt/AlertException.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertException.java
rename to crypto/src/main/java/org/conscrypt/AlertException.java
index fdc1cd9..a483021 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertException.java
+++ b/crypto/src/main/java/org/conscrypt/AlertException.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import javax.net.ssl.SSLException;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertProtocol.java b/crypto/src/main/java/org/conscrypt/AlertProtocol.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertProtocol.java
rename to crypto/src/main/java/org/conscrypt/AlertProtocol.java
index 2097bb0..0330e79 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertProtocol.java
+++ b/crypto/src/main/java/org/conscrypt/AlertProtocol.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 /**
  * This class encapsulates the functionality of Alert Protocol.
@@ -155,9 +155,8 @@
      * of the income TSL record: if it contains alert message from another
      * peer, or if warning alert occured during the processing of the
      * message and this warning should be sent to another peer.
-     * @param   level:  alert level code
-     * @param   description: alert description code
-     * @return
+     * @param level alert level code
+     * @param description alert description code
      */
     protected void alert(byte level, byte description) {
         if (logger != null) {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Appendable.java b/crypto/src/main/java/org/conscrypt/Appendable.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Appendable.java
rename to crypto/src/main/java/org/conscrypt/Appendable.java
index 098b60c..d22c5a8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Appendable.java
+++ b/crypto/src/main/java/org/conscrypt/Appendable.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 /**
  * This interface represents the ability of the input stream related classes to provide additional
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ByteArray.java b/crypto/src/main/java/org/conscrypt/ByteArray.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ByteArray.java
rename to crypto/src/main/java/org/conscrypt/ByteArray.java
index 8a000c5..be682de 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ByteArray.java
+++ b/crypto/src/main/java/org/conscrypt/ByteArray.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.util.Arrays;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertPinManager.java b/crypto/src/main/java/org/conscrypt/CertPinManager.java
similarity index 77%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertPinManager.java
rename to crypto/src/main/java/org/conscrypt/CertPinManager.java
index 4cdd8d2..22578fc 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertPinManager.java
+++ b/crypto/src/main/java/org/conscrypt/CertPinManager.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -22,8 +22,8 @@
 import java.security.cert.X509Certificate;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
-import javax.net.ssl.DefaultHostnameVerifier;
 import libcore.io.IoUtils;
 import libcore.util.BasicLruCache;
 
@@ -36,7 +36,6 @@
 
     private final Map<String, PinListEntry> entries = new HashMap<String, PinListEntry>();
     private final BasicLruCache<String, String> hostnameCache = new BasicLruCache<String, String>(10);
-    private final DefaultHostnameVerifier verifier = new DefaultHostnameVerifier();
 
     private boolean initialized = false;
     private static final boolean DEBUG = false;
@@ -166,13 +165,59 @@
                 continue;
             }
             // now verify that the CN matches at all
-            if (verifier.verifyHostName(hostname, cn)) {
+            if (isHostnameMatchedBy(hostname, cn)) {
                 bestMatch = cn;
             }
         }
         return bestMatch;
     }
 
+    /**
+     * Returns true if {@code hostName} matches the name or pattern {@code cn}.
+     *
+     * @param hostName lowercase host name.
+     * @param cn certificate host name. May include wildcards like
+     *            {@code *.android.com}.
+     */
+    private static boolean isHostnameMatchedBy(String hostName, String cn) {
+        if (hostName == null || hostName.isEmpty() || cn == null || cn.isEmpty()) {
+            return false;
+        }
+
+        cn = cn.toLowerCase(Locale.US);
+
+        if (!cn.contains("*")) {
+            return hostName.equals(cn);
+        }
+
+        if (cn.startsWith("*.") && hostName.regionMatches(0, cn, 2, cn.length() - 2)) {
+            return true; // "*.foo.com" matches "foo.com"
+        }
+
+        int asterisk = cn.indexOf('*');
+        int dot = cn.indexOf('.');
+        if (asterisk > dot) {
+            return false; // malformed; wildcard must be in the first part of
+                          // the cn
+        }
+
+        if (!hostName.regionMatches(0, cn, 0, asterisk)) {
+            return false; // prefix before '*' doesn't match
+        }
+
+        int suffixLength = cn.length() - (asterisk + 1);
+        int suffixStart = hostName.length() - suffixLength;
+        if (hostName.indexOf('.', asterisk) < suffixStart) {
+            return false; // wildcard '*' can't match a '.'
+        }
+
+        if (!hostName.regionMatches(suffixStart, cn, asterisk + 1, suffixLength)) {
+            return false; // suffix after '*' doesn't match
+        }
+
+        return true;
+    }
+
     private static void log(String s, Exception e) {
         if (DEBUG) {
             System.out.println("PINFILE: " + s);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateMessage.java b/crypto/src/main/java/org/conscrypt/CertificateMessage.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateMessage.java
rename to crypto/src/main/java/org/conscrypt/CertificateMessage.java
index 9bc28a0..0c0e092 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateMessage.java
+++ b/crypto/src/main/java/org/conscrypt/CertificateMessage.java
@@ -15,10 +15,9 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
-import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
@@ -158,8 +157,6 @@
 
     /**
      * Returns message type
-     *
-     * @return
      */
     @Override
     public int getType() {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java b/crypto/src/main/java/org/conscrypt/CertificateRequest.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
rename to crypto/src/main/java/org/conscrypt/CertificateRequest.java
index f3be44c..6d08cc2 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
+++ b/crypto/src/main/java/org/conscrypt/CertificateRequest.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.security.cert.X509Certificate;
@@ -132,8 +132,6 @@
 
     /**
      * Returns message type
-     *
-     * @return
      */
     @Override
     public int getType() {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateVerify.java b/crypto/src/main/java/org/conscrypt/CertificateVerify.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateVerify.java
rename to crypto/src/main/java/org/conscrypt/CertificateVerify.java
index aa4402e..8ba394a 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateVerify.java
+++ b/crypto/src/main/java/org/conscrypt/CertificateVerify.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 
@@ -82,8 +82,6 @@
 
     /**
      * Returns message type
-     *
-     * @return
      */
     @Override
     public int getType() {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzer.java b/crypto/src/main/java/org/conscrypt/ChainStrengthAnalyzer.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzer.java
rename to crypto/src/main/java/org/conscrypt/ChainStrengthAnalyzer.java
index 29b55a6..dc4f9b7 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzer.java
+++ b/crypto/src/main/java/org/conscrypt/ChainStrengthAnalyzer.java
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.security.interfaces.RSAPublicKey;
-import java.util.List;
 
 public final class ChainStrengthAnalyzer {
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java b/crypto/src/main/java/org/conscrypt/CipherSuite.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
rename to crypto/src/main/java/org/conscrypt/CipherSuite.java
index c20a0b9..6d2a3e8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
+++ b/crypto/src/main/java/org/conscrypt/CipherSuite.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.GeneralSecurityException;
 import java.util.Hashtable;
@@ -971,7 +971,6 @@
 
     /**
      * Returns true if cipher suite is anonymous
-     * @return
      */
     public boolean isAnonymous() {
         if (keyExchange == KEY_EXCHANGE_DH_anon
@@ -984,7 +983,6 @@
 
     /**
      * Returns array of supported CipherSuites
-     * @return
      */
     public static CipherSuite[] getSupported() {
         return SUPPORTED_CIPHER_SUITES;
@@ -992,7 +990,6 @@
 
     /**
      * Returns array of supported cipher suites names
-     * @return
      */
     public static String[] getSupportedCipherSuiteNames() {
         return SUPPORTED_CIPHER_SUITE_NAMES.clone();
@@ -1000,7 +997,6 @@
 
     /**
      * Returns cipher suite name
-     * @return
      */
     public String getName() {
         return name;
@@ -1008,7 +1004,6 @@
 
     /**
      * Returns cipher suite code as byte array
-     * @return
      */
     public byte[] toBytes() {
         return cipherSuiteCode;
@@ -1024,7 +1019,6 @@
 
     /**
      * Returns cipher algorithm name
-     * @return
      */
     public String getBulkEncryptionAlgorithm() {
         return cipherName;
@@ -1032,7 +1026,6 @@
 
     /**
      * Returns cipher block size
-     * @return
      */
     public int getBlockSize() {
         return blockSize;
@@ -1040,7 +1033,6 @@
 
     /**
      * Returns MAC algorithm name
-     * @return
      */
     public String getHmacName() {
         return hmacName;
@@ -1048,7 +1040,6 @@
 
     /**
      * Returns hash algorithm name
-     * @return
      */
     public String getHashName() {
         return hashName;
@@ -1056,7 +1047,6 @@
 
     /**
      * Returns hash size
-     * @return
      */
     public int getMACLength() {
         return hashSize;
@@ -1064,7 +1054,6 @@
 
     /**
      * Indicates whether this cipher suite is exportable
-     * @return
      */
     public boolean isExportable() {
         return isExportable;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java b/crypto/src/main/java/org/conscrypt/ClientHandshakeImpl.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
rename to crypto/src/main/java/org/conscrypt/ClientHandshakeImpl.java
index 5d2521b..8706ec0 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
+++ b/crypto/src/main/java/org/conscrypt/ClientHandshakeImpl.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.security.Key;
@@ -322,7 +322,7 @@
      * Processes SSLv2 Hello message.
      * SSLv2 client hello message message is an unexpected message
      * for client side of handshake protocol.
-     * @ see TLS 1.0 spec., E.1. Version 2 client hello
+     * See TLS 1.0 spec., E.1. Version 2 client hello
      * @param bytes
      */
     @Override
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHello.java b/crypto/src/main/java/org/conscrypt/ClientHello.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHello.java
rename to crypto/src/main/java/org/conscrypt/ClientHello.java
index 1bded5d..2bf9f5f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHello.java
+++ b/crypto/src/main/java/org/conscrypt/ClientHello.java
@@ -15,13 +15,13 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.security.SecureRandom;
 import java.util.Arrays;
 import libcore.io.Streams;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
 
 /**
  * Represents Client Hello message
@@ -199,7 +199,6 @@
 
     /**
      * Returns message type
-     * @return
      */
     @Override
     public int getType() {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientKeyExchange.java b/crypto/src/main/java/org/conscrypt/ClientKeyExchange.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientKeyExchange.java
rename to crypto/src/main/java/org/conscrypt/ClientKeyExchange.java
index 2bae8d0..5cad36b 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientKeyExchange.java
+++ b/crypto/src/main/java/org/conscrypt/ClientKeyExchange.java
@@ -15,12 +15,12 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.math.BigInteger;
 import libcore.io.Streams;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
 
 /**
  * Represents client key exchange message
@@ -133,7 +133,6 @@
 
     /**
      * Returns message type
-     * @return
      */
     @Override
     public int getType() {
@@ -142,7 +141,6 @@
 
     /**
      * Returns true if the message is empty (in case of implicit DH Yc)
-     * @return
      */
     public boolean isEmpty() {
         return (exchange_keys.length == 0);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java b/crypto/src/main/java/org/conscrypt/ClientSessionContext.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
rename to crypto/src/main/java/org/conscrypt/ClientSessionContext.java
index 0b358aa..27a39cf 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
+++ b/crypto/src/main/java/org/conscrypt/ClientSessionContext.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionState.java b/crypto/src/main/java/org/conscrypt/ConnectionState.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionState.java
rename to crypto/src/main/java/org/conscrypt/ConnectionState.java
index eed6dee..82fbf3c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionState.java
+++ b/crypto/src/main/java/org/conscrypt/ConnectionState.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import javax.crypto.Cipher;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateSSLv3.java b/crypto/src/main/java/org/conscrypt/ConnectionStateSSLv3.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateSSLv3.java
rename to crypto/src/main/java/org/conscrypt/ConnectionStateSSLv3.java
index 480d77d..84b8483 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateSSLv3.java
+++ b/crypto/src/main/java/org/conscrypt/ConnectionStateSSLv3.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.GeneralSecurityException;
 import java.security.MessageDigest;
@@ -52,7 +52,7 @@
     /**
      * Creates the instance of SSL v3 Connection State. All of the
      * security parameters are provided by session object.
-     * @param   session: the sessin object which incapsulates
+     * @param session the sessin object which incapsulates
      * all of the security parameters established by handshake protocol.
      * The key calculation for the state is done according
      * to the SSL v3 Protocol specification.
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateTLS.java b/crypto/src/main/java/org/conscrypt/ConnectionStateTLS.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateTLS.java
rename to crypto/src/main/java/org/conscrypt/ConnectionStateTLS.java
index 42169da..a4d9de8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateTLS.java
+++ b/crypto/src/main/java/org/conscrypt/ConnectionStateTLS.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.GeneralSecurityException;
 import java.util.Arrays;
@@ -74,7 +74,7 @@
     /**
      * Creates the instance of TLS v1 Connection State. All of the
      * security parameters are provided by session object.
-     * @param   session: the sessin object which incapsulates
+     * @param session the sessin object which incapsulates
      * all of the security parameters established by handshake protocol.
      * The key calculation for the state is done according
      * to the TLS v 1.0 Protocol specification.
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ContentType.java b/crypto/src/main/java/org/conscrypt/ContentType.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ContentType.java
rename to crypto/src/main/java/org/conscrypt/ContentType.java
index 69704f5..b09f029 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ContentType.java
+++ b/crypto/src/main/java/org/conscrypt/ContentType.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 /**
  * This class incapsulates the constants determining the
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DHParameters.java b/crypto/src/main/java/org/conscrypt/DHParameters.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DHParameters.java
rename to crypto/src/main/java/org/conscrypt/DHParameters.java
index 4988d5e..7a742b2 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DHParameters.java
+++ b/crypto/src/main/java/org/conscrypt/DHParameters.java
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 /**
  * This class contains well-known primes
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DataStream.java b/crypto/src/main/java/org/conscrypt/DataStream.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DataStream.java
rename to crypto/src/main/java/org/conscrypt/DataStream.java
index ffc8612..d65b01a 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DataStream.java
+++ b/crypto/src/main/java/org/conscrypt/DataStream.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 /**
  * This interface represents the ability of the
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java b/crypto/src/main/java/org/conscrypt/DefaultSSLContextImpl.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java
rename to crypto/src/main/java/org/conscrypt/DefaultSSLContextImpl.java
index 66b9ebe..c90787f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java
+++ b/crypto/src/main/java/org/conscrypt/DefaultSSLContextImpl.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.BufferedInputStream;
 import java.io.FileInputStream;
@@ -25,7 +25,7 @@
 import java.security.KeyManagementException;
 import java.security.KeyStore;
 import java.security.SecureRandom;
-import java.security.Security;
+
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.TrustManager;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DelegatedTask.java b/crypto/src/main/java/org/conscrypt/DelegatedTask.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DelegatedTask.java
rename to crypto/src/main/java/org/conscrypt/DelegatedTask.java
index 0e13bc2..8eab2ea 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DelegatedTask.java
+++ b/crypto/src/main/java/org/conscrypt/DelegatedTask.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 /**
  * Delegated Runnable task for SSLEngine
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DigitalSignature.java b/crypto/src/main/java/org/conscrypt/DigitalSignature.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DigitalSignature.java
rename to crypto/src/main/java/org/conscrypt/DigitalSignature.java
index ade2c7a..e24056e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DigitalSignature.java
+++ b/crypto/src/main/java/org/conscrypt/DigitalSignature.java
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.DigestException;
 import java.security.InvalidKeyException;
@@ -30,7 +30,7 @@
 import javax.crypto.IllegalBlockSizeException;
 import javax.crypto.NoSuchPaddingException;
 import javax.net.ssl.SSLException;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
 
 /**
  * This class represents Signature type, as described in TLS v 1.0 Protocol
@@ -66,17 +66,17 @@
 
     /**
      * Create Signature type
-     * @param keyExchange
+     * @param algorithm the key algorithm used for the signature
      */
-    public DigitalSignature(String authType) {
+    public DigitalSignature(String algorithm) {
         try {
             sha = MessageDigest.getInstance("SHA-1");
 
-            if ("RSA".equals(authType)) {
+            if ("RSA".equals(algorithm)) {
                 md5 = MessageDigest.getInstance("MD5");
                 cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
                 signature = null;
-            } else if ("DSA".equals(authType)) {
+            } else if ("DSA".equals(algorithm)) {
                 // SignatureAlgorithm is dsa
                 signature = Signature.getInstance("NONEwithDSA");
                 cipher = null;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java b/crypto/src/main/java/org/conscrypt/EndOfBufferException.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
rename to crypto/src/main/java/org/conscrypt/EndOfBufferException.java
index 7fe2d7f..acd3417 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
+++ b/crypto/src/main/java/org/conscrypt/EndOfBufferException.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfSourceException.java b/crypto/src/main/java/org/conscrypt/EndOfSourceException.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfSourceException.java
rename to crypto/src/main/java/org/conscrypt/EndOfSourceException.java
index 3874709..4789cd8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfSourceException.java
+++ b/crypto/src/main/java/org/conscrypt/EndOfSourceException.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCache.java b/crypto/src/main/java/org/conscrypt/FileClientSessionCache.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCache.java
rename to crypto/src/main/java/org/conscrypt/FileClientSessionCache.java
index 0f1fe24..e4dab13 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCache.java
+++ b/crypto/src/main/java/org/conscrypt/FileClientSessionCache.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.DataInputStream;
 import java.io.File;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Finished.java b/crypto/src/main/java/org/conscrypt/Finished.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Finished.java
rename to crypto/src/main/java/org/conscrypt/Finished.java
index fc89d48..e0b7eaa 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Finished.java
+++ b/crypto/src/main/java/org/conscrypt/Finished.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 
@@ -63,7 +63,6 @@
 
     /**
      * Returns message type
-     * @return
      */
     @Override
     public int getType() {
@@ -72,7 +71,6 @@
 
     /**
      * Returns verify data
-     * @return
      */
     public byte[] getData() {
         return data;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Handshake.java b/crypto/src/main/java/org/conscrypt/Handshake.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Handshake.java
rename to crypto/src/main/java/org/conscrypt/Handshake.java
index b61a96c..7cee71b 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Handshake.java
+++ b/crypto/src/main/java/org/conscrypt/Handshake.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 /**
  *
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeIODataStream.java b/crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeIODataStream.java
rename to crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java
index ee9f667..0723820 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeIODataStream.java
+++ b/crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.PrintStream;
@@ -60,7 +60,7 @@
  * TLS v 1 specification at http://www.ietf.org/rfc/rfc2246.txt.
  */
 public class HandshakeIODataStream
-        extends SSLInputStream implements org.apache.harmony.xnet.provider.jsse.Appendable, DataStream {
+        extends SSLInputStream implements org.conscrypt.Appendable, DataStream {
 
     // Objects are used to compute digests of data passed
     // during the handshake phase
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java b/crypto/src/main/java/org/conscrypt/HandshakeProtocol.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
rename to crypto/src/main/java/org/conscrypt/HandshakeProtocol.java
index f8016f1..73d00ae 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
+++ b/crypto/src/main/java/org/conscrypt/HandshakeProtocol.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.math.BigInteger;
 import java.security.GeneralSecurityException;
@@ -180,7 +180,6 @@
 
     /**
      * Start session negotiation
-     * @param session
      */
     public abstract void start();
 
@@ -198,7 +197,6 @@
 
     /**
      * Returns handshake status
-     * @return
      */
     public SSLEngineResult.HandshakeStatus getStatus() {
         if (io_stream.hasData() || needSendCCSpec ||
@@ -260,8 +258,7 @@
     public abstract void unwrapSSLv2(byte[] bytes);
 
     /**
-     * Proceses outbound handshake messages
-     * @return
+     * Processes outbound handshake messages
      */
     public byte[] wrap() {
         if (delegatedTaskErr != null) {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HelloRequest.java b/crypto/src/main/java/org/conscrypt/HelloRequest.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HelloRequest.java
rename to crypto/src/main/java/org/conscrypt/HelloRequest.java
index 69c146c..20efbfd 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HelloRequest.java
+++ b/crypto/src/main/java/org/conscrypt/HelloRequest.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java b/crypto/src/main/java/org/conscrypt/JSSEProvider.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
rename to crypto/src/main/java/org/conscrypt/JSSEProvider.java
index 58dad45..ad56976 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
+++ b/crypto/src/main/java/org/conscrypt/JSSEProvider.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.Provider;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerFactoryImpl.java b/crypto/src/main/java/org/conscrypt/KeyManagerFactoryImpl.java
similarity index 86%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/KeyManagerFactoryImpl.java
index 261f3c7..3ad9be9 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/KeyManagerFactoryImpl.java
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -29,11 +29,11 @@
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactorySpi;
 import javax.net.ssl.ManagerFactoryParameters;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
 
 /**
  * KeyManagerFactory implementation.
- * @see javax.net.ssl.KeyManagerFactorySpi
+ * @see KeyManagerFactorySpi
  */
 public class KeyManagerFactoryImpl extends KeyManagerFactorySpi {
 
@@ -44,11 +44,10 @@
     private char[] pwd;
 
     /**
-     * @see javax.net.ssl.KeyManagerFactorySpi#engineInit(KeyStore ks, char[]
-     *      password)
+     * @see KeyManagerFactorySpi#engineInit(KeyStore ks, char[] password)
      */
     @Override
-    public void engineInit(KeyStore ks, char[] password)
+    protected void engineInit(KeyStore ks, char[] password)
             throws KeyStoreException, NoSuchAlgorithmException,
             UnrecoverableKeyException {
         if (ks != null) {
@@ -93,11 +92,10 @@
     }
 
     /**
-     * @see javax.net.ssl.KeyManagerFactorySpi#engineInit(ManagerFactoryParameters
-     *      spec)
+     * @see KeyManagerFactorySpi#engineInit(ManagerFactoryParameters spec)
      */
     @Override
-    public void engineInit(ManagerFactoryParameters spec)
+    protected void engineInit(ManagerFactoryParameters spec)
             throws InvalidAlgorithmParameterException {
         throw new InvalidAlgorithmParameterException(
                 "ManagerFactoryParameters not supported");
@@ -105,10 +103,10 @@
     }
 
     /**
-     * @see javax.net.ssl.KeyManagerFactorySpi#engineGetKeyManagers()
+     * @see KeyManagerFactorySpi#engineGetKeyManagers()
      */
     @Override
-    public KeyManager[] engineGetKeyManagers() {
+    protected KeyManager[] engineGetKeyManagers() {
         if (keyStore == null) {
             throw new IllegalStateException("KeyManagerFactory is not initialized");
         }
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java b/crypto/src/main/java/org/conscrypt/KeyManagerImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
rename to crypto/src/main/java/org/conscrypt/KeyManagerImpl.java
index 8ccf687..ed37fd6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
+++ b/crypto/src/main/java/org/conscrypt/KeyManagerImpl.java
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.net.Socket;
 import java.security.KeyStore;
@@ -190,7 +190,7 @@
                     continue;
                 }
                 // check that a certificate in the chain was issued by one of the specified issuers
-                loop: for (Certificate certFromChain : chain) {
+                for (Certificate certFromChain : chain) {
                     if (!(certFromChain instanceof X509Certificate)) {
                         // skip non-X509Certificates
                         continue;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Logger.java b/crypto/src/main/java/org/conscrypt/Logger.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Logger.java
rename to crypto/src/main/java/org/conscrypt/Logger.java
index 2fbbef7..9241c8a 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Logger.java
+++ b/crypto/src/main/java/org/conscrypt/Logger.java
@@ -15,11 +15,11 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.PrintStream;
 import java.util.Locale;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
 
 /**
  * This class provides debug logging for JSSE provider implementation
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Message.java b/crypto/src/main/java/org/conscrypt/Message.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Message.java
rename to crypto/src/main/java/org/conscrypt/Message.java
index bd97136..3b932d0 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Message.java
+++ b/crypto/src/main/java/org/conscrypt/Message.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLHandshakeException;
@@ -33,13 +33,11 @@
 
     /**
      * Returns message type
-     * @return
      */
     abstract int getType();
 
     /**
      * Returns message length
-     * @return
      */
     public int length() {
         return length;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java b/crypto/src/main/java/org/conscrypt/NativeCrypto.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
rename to crypto/src/main/java/org/conscrypt/NativeCrypto.java
index 9991af4..9094935 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
+++ b/crypto/src/main/java/org/conscrypt/NativeCrypto.java
@@ -14,22 +14,19 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.SocketTimeoutException;
-import java.nio.ByteOrder;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
 import java.security.SignatureException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateParsingException;
-import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.HashMap;
@@ -40,7 +37,6 @@
 import javax.crypto.IllegalBlockSizeException;
 import javax.net.ssl.SSLException;
 import javax.security.auth.x500.X500Principal;
-import libcore.io.Memory;
 
 /**
  * Provides the Java side of our JNI glue for OpenSSL.
@@ -49,6 +45,15 @@
 
     // --- OpenSSL library initialization --------------------------------------
     static {
+        /*
+         * If we're compiled as part of Android, we don't need to explicitly
+         * call loadLibrary. Detect this by looking for the jarjar'd package
+         * name.
+         */
+        if (!"com.android.org.conscrypt".equals(NativeCrypto.class.getPackage().getName())) {
+            System.loadLibrary("conscrypt_jni");
+        }
+
         clinit();
     }
 
@@ -340,7 +345,11 @@
     private static int X509_NAME_hash(X500Principal principal, String algorithm) {
         try {
             byte[] digest = MessageDigest.getInstance(algorithm).digest(principal.getEncoded());
-            return Memory.peekInt(digest, 0, ByteOrder.LITTLE_ENDIAN);
+            int offset = 0;
+            return (((digest[offset++] & 0xff) <<  0) |
+                    ((digest[offset++] & 0xff) <<  8) |
+                    ((digest[offset++] & 0xff) << 16) |
+                    ((digest[offset  ] & 0xff) << 24));
         } catch (NoSuchAlgorithmException e) {
             throw new AssertionError(e);
         }
@@ -437,6 +446,8 @@
 
     public static native int get_X509_ex_flags(long x509ctx);
 
+    public static native int X509_check_issued(long ctx, long ctx2);
+
     // --- X509 EXFLAG ---------------------------------------------------------
 
     public static final int EXFLAG_CA = 0x10;
@@ -762,27 +773,7 @@
 
     public static native byte[] SSL_get_tls_channel_id(long ssl) throws SSLException;
 
-    public static native void SSL_use_OpenSSL_PrivateKey_for_tls_channel_id(long ssl, long pkey)
-            throws SSLException;
-
-    public static native void SSL_use_PKCS8_PrivateKey_for_tls_channel_id(
-            long ssl, byte[] pkcs8EncodedPrivateKey) throws SSLException;
-
-    public static void SSL_set1_tls_channel_id(long ssl, PrivateKey privateKey)
-            throws SSLException {
-        if (privateKey == null) {
-            throw new NullPointerException("privateKey == null");
-        } else if (privateKey instanceof OpenSSLECPrivateKey) {
-            OpenSSLKey openSslPrivateKey = ((OpenSSLECPrivateKey) privateKey).getOpenSSLKey();
-            SSL_use_OpenSSL_PrivateKey_for_tls_channel_id(ssl, openSslPrivateKey.getPkeyContext());
-        } else if ("PKCS#8".equals(privateKey.getFormat())) {
-            byte[] pkcs8EncodedKey = privateKey.getEncoded();
-            SSL_use_PKCS8_PrivateKey_for_tls_channel_id(ssl, pkcs8EncodedKey);
-        } else {
-            throw new SSLException("Unsupported Channel ID private key type:" +
-                    " class: " + privateKey.getClass() + ", format: " + privateKey.getFormat());
-        }
-    }
+    public static native void SSL_set1_tls_channel_id(long ssl, long pkey);
 
     public static byte[][] encodeCertificates(Certificate[] certificates)
             throws CertificateEncodingException {
@@ -795,21 +786,10 @@
 
     public static native void SSL_use_certificate(long ssl, byte[][] asn1DerEncodedCertificateChain);
 
-    public static native void SSL_use_OpenSSL_PrivateKey(long ssl, long pkey);
-
-    public static native void SSL_use_PrivateKey(long ssl, byte[] pkcs8EncodedPrivateKey);
+    public static native void SSL_use_PrivateKey(long ssl, long pkey);
 
     public static native void SSL_check_private_key(long ssl) throws SSLException;
 
-    public static byte[][] encodeIssuerX509Principals(X509Certificate[] certificates)
-            throws CertificateEncodingException {
-        byte[][] principalBytes = new byte[certificates.length][];
-        for (int i = 0; i < certificates.length; i++) {
-            principalBytes[i] = certificates[i].getIssuerX500Principal().getEncoded();
-        }
-        return principalBytes;
-    }
-
     public static native void SSL_set_client_CA_list(long ssl, byte[][] asn1DerEncodedX500Principals);
 
     public static native long SSL_get_mode(long ssl);
@@ -972,14 +952,29 @@
     public static native void SSL_CTX_disable_npn(long sslCtxNativePointer);
 
     /**
-     * Returns the sslSessionNativePointer of the negotiated session
+     * For clients, sets the list of supported ALPN protocols in wire-format
+     * (length-prefixed 8-bit strings) on an SSL context.
+     */
+    public static native int SSL_CTX_set_alpn_protos(long sslCtxPointer, byte[] protos);
+
+    /**
+     * Returns the selected ALPN protocol. If the server did not select a
+     * protocol, {@code null} will be returned.
+     */
+    public static native byte[] SSL_get0_alpn_selected(long sslPointer);
+
+    /**
+     * Returns the sslSessionNativePointer of the negotiated session. If this is
+     * a server negotiation, supplying the {@code alpnProtocols} will enable
+     * ALPN negotiation.
      */
     public static native int SSL_do_handshake(long sslNativePointer,
                                               FileDescriptor fd,
                                               SSLHandshakeCallbacks shc,
                                               int timeoutMillis,
                                               boolean client_mode,
-                                              byte[] npnProtocols)
+                                              byte[] npnProtocols,
+                                              byte[] alpnProtocols)
         throws SSLException, SocketTimeoutException, CertificateException;
 
     public static native byte[] SSL_get_npn_negotiated_protocol(long sslNativePointer);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLBIOInputStream.java b/crypto/src/main/java/org/conscrypt/OpenSSLBIOInputStream.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLBIOInputStream.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLBIOInputStream.java
index 54e5798..26971d5 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLBIOInputStream.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLBIOInputStream.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.FilterInputStream;
 import java.io.IOException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipher.java b/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipher.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
index 6ca8835..632f9e2 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipher.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.AlgorithmParameters;
 import java.security.InvalidAlgorithmParameterException;
@@ -31,7 +31,6 @@
 import java.security.spec.X509EncodedKeySpec;
 import java.util.Arrays;
 import java.util.Locale;
-
 import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
 import javax.crypto.CipherSpi;
@@ -41,8 +40,7 @@
 import javax.crypto.ShortBufferException;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
-
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
 
 public abstract class OpenSSLCipher extends CipherSpi {
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherContext.java b/crypto/src/main/java/org/conscrypt/OpenSSLCipherContext.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherContext.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLCipherContext.java
index eb99334..ffbcad4 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherContext.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLCipherContext.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 class OpenSSLCipherContext {
     private final long context;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherRSA.java b/crypto/src/main/java/org/conscrypt/OpenSSLCipherRSA.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherRSA.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLCipherRSA.java
index ddf2e0d..9e2f426 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherRSA.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLCipherRSA.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.AlgorithmParameters;
 import java.security.InvalidAlgorithmParameterException;
@@ -33,6 +33,7 @@
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.Arrays;
+import java.util.Locale;
 import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
 import javax.crypto.CipherSpi;
@@ -40,7 +41,7 @@
 import javax.crypto.NoSuchPaddingException;
 import javax.crypto.ShortBufferException;
 import javax.crypto.spec.SecretKeySpec;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
 
 public abstract class OpenSSLCipherRSA extends CipherSpi {
     /**
@@ -85,7 +86,7 @@
 
     @Override
     protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
-        final String modeUpper = mode.toUpperCase();
+        final String modeUpper = mode.toUpperCase(Locale.ROOT);
         if ("NONE".equals(modeUpper) || "ECB".equals(modeUpper)) {
             return;
         }
@@ -95,7 +96,7 @@
 
     @Override
     protected void engineSetPadding(String padding) throws NoSuchPaddingException {
-        final String paddingUpper = padding.toUpperCase();
+        final String paddingUpper = padding.toUpperCase(Locale.ROOT);
         if ("PKCS1PADDING".equals(paddingUpper)) {
             this.padding = NativeCrypto.RSA_PKCS1_PADDING;
             return;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLContextImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLContextImpl.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLContextImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLContextImpl.java
index b4e4a46..6b0e5f9 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLContextImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLContextImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.security.GeneralSecurityException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyFactory.java b/crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyFactory.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyFactory.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyFactory.java
index efa4747..a9f7067 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyFactory.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyFactory.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.math.BigInteger;
 import java.security.InvalidKeyException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyPairGenerator.java b/crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyPairGenerator.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyPairGenerator.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyPairGenerator.java
index aa0b317..3428fcc 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyPairGenerator.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyPairGenerator.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.math.BigInteger;
 import java.security.InvalidAlgorithmParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAParams.java b/crypto/src/main/java/org/conscrypt/OpenSSLDSAParams.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAParams.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDSAParams.java
index df9968b..fd0edf7 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAParams.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDSAParams.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.math.BigInteger;
 import java.security.interfaces.DSAParams;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPrivateKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLDSAPrivateKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPrivateKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDSAPrivateKey.java
index df62c6d..0fc4db7 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPrivateKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDSAPrivateKey.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPublicKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLDSAPublicKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPublicKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDSAPublicKey.java
index be9ff83..1c0bf74 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPublicKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDSAPublicKey.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDigestContext.java b/crypto/src/main/java/org/conscrypt/OpenSSLDigestContext.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDigestContext.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDigestContext.java
index b3bd1a0..b11a862 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDigestContext.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDigestContext.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 public class OpenSSLDigestContext {
     private final long context;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECDHKeyAgreement.java b/crypto/src/main/java/org/conscrypt/OpenSSLECDHKeyAgreement.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECDHKeyAgreement.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECDHKeyAgreement.java
index 5146156..0d8729c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECDHKeyAgreement.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECDHKeyAgreement.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
@@ -24,7 +24,6 @@
 import java.security.PublicKey;
 import java.security.SecureRandom;
 import java.security.spec.AlgorithmParameterSpec;
-
 import javax.crypto.KeyAgreementSpi;
 import javax.crypto.SecretKey;
 import javax.crypto.ShortBufferException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECGroupContext.java b/crypto/src/main/java/org/conscrypt/OpenSSLECGroupContext.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECGroupContext.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECGroupContext.java
index 173ce79..f7f52a6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECGroupContext.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECGroupContext.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.math.BigInteger;
 import java.security.InvalidAlgorithmParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyFactory.java b/crypto/src/main/java/org/conscrypt/OpenSSLECKeyFactory.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyFactory.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECKeyFactory.java
index e4673a5..b39a611 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyFactory.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECKeyFactory.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.math.BigInteger;
 import java.security.InvalidKeyException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyPairGenerator.java b/crypto/src/main/java/org/conscrypt/OpenSSLECKeyPairGenerator.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyPairGenerator.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECKeyPairGenerator.java
index bea46e6..21c8984 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyPairGenerator.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECKeyPairGenerator.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPointContext.java b/crypto/src/main/java/org/conscrypt/OpenSSLECPointContext.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPointContext.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECPointContext.java
index 7c5c067..49bdaf1 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPointContext.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECPointContext.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.math.BigInteger;
 import java.security.spec.ECPoint;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPrivateKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLECPrivateKey.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPrivateKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECPrivateKey.java
index b0be998..a4b41db 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPrivateKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECPrivateKey.java
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.NotSerializableException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.interfaces.ECPrivateKey;
 import java.security.spec.ECParameterSpec;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPublicKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLECPublicKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPublicKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECPublicKey.java
index b591336..8f3a0c6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPublicKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECPublicKey.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLEngine.java b/crypto/src/main/java/org/conscrypt/OpenSSLEngine.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLEngine.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLEngine.java
index 4e02aad..380e73f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLEngine.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLEngine.java
@@ -14,12 +14,11 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
-
 import javax.crypto.SecretKey;
 
 public class OpenSSLEngine {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLKey.java
similarity index 91%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLKey.java
index 921a4b6..fa9a258 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLKey.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
+import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
-
 import javax.crypto.SecretKey;
 
 public class OpenSSLKey {
@@ -65,6 +65,18 @@
         return alias;
     }
 
+    public static OpenSSLKey fromPrivateKey(PrivateKey key) throws InvalidKeyException {
+        if (key instanceof OpenSSLKeyHolder) {
+            return ((OpenSSLKeyHolder) key).getOpenSSLKey();
+        }
+
+        if ("PKCS#8".equals(key.getFormat())) {
+            return new OpenSSLKey(NativeCrypto.d2i_PKCS8_PRIV_KEY_INFO(key.getEncoded()));
+        } else {
+            throw new InvalidKeyException("Unknown key format " + key.getFormat());
+        }
+    }
+
     public PublicKey getPublicKey() throws NoSuchAlgorithmException {
         switch (NativeCrypto.EVP_PKEY_type(ctx)) {
             case NativeCrypto.EVP_PKEY_RSA:
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java b/crypto/src/main/java/org/conscrypt/OpenSSLKeyHolder.java
similarity index 93%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLKeyHolder.java
index 548e9c5..09af21c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLKeyHolder.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 public interface OpenSSLKeyHolder {
     public OpenSSLKey getOpenSSLKey();
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMac.java b/crypto/src/main/java/org/conscrypt/OpenSSLMac.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMac.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLMac.java
index 697af5a..824e6b9 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMac.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLMac.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMessageDigestJDK.java b/crypto/src/main/java/org/conscrypt/OpenSSLMessageDigestJDK.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMessageDigestJDK.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLMessageDigestJDK.java
index 9d59a7c..763ff65 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMessageDigestJDK.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLMessageDigestJDK.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
diff --git a/crypto/src/main/java/org/conscrypt/OpenSSLProvider.java b/crypto/src/main/java/org/conscrypt/OpenSSLProvider.java
new file mode 100644
index 0000000..7314478
--- /dev/null
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLProvider.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2010 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.conscrypt;
+
+import java.security.Provider;
+
+/**
+ * Provider that goes through OpenSSL for operations.
+ * <p>
+ * Every algorithm should have its IANA assigned OID as an alias. See the following URLs for each type:
+ * <ul>
+ * <li><a href="http://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml">Hash functions</a></li>
+ * <li><a href="http://www.iana.org/assignments/dssc/dssc.xml">Signature algorithms</a></li>
+ * <li><a href="http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html">NIST cryptographic algorithms</a></li>
+ * </ul>
+ */
+public final class OpenSSLProvider extends Provider {
+    private static final long serialVersionUID = 2996752495318905136L;
+
+    public static final String PROVIDER_NAME = "AndroidOpenSSL";
+
+    public OpenSSLProvider() {
+        super(PROVIDER_NAME, 1.0, "Android's OpenSSL-backed security provider");
+
+        final String prefix = getClass().getPackage().getName() + ".";
+
+        /* === SSL Contexts === */
+        final String classOpenSSLContextImpl = prefix + "OpenSSLContextImpl";
+        put("SSLContext.SSL", classOpenSSLContextImpl);
+        put("SSLContext.SSLv3", classOpenSSLContextImpl);
+        put("SSLContext.TLS", classOpenSSLContextImpl);
+        put("SSLContext.TLSv1", classOpenSSLContextImpl);
+        put("SSLContext.TLSv1.1", classOpenSSLContextImpl);
+        put("SSLContext.TLSv1.2", classOpenSSLContextImpl);
+        put("SSLContext.Default", prefix + "DefaultSSLContextImpl");
+
+        /* === Message Digests === */
+        put("MessageDigest.SHA-1", prefix + "OpenSSLMessageDigestJDK$SHA1");
+        put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
+        put("Alg.Alias.MessageDigest.SHA", "SHA-1");
+        put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA-1");
+
+        put("MessageDigest.SHA-256", prefix + "OpenSSLMessageDigestJDK$SHA256");
+        put("Alg.Alias.MessageDigest.SHA256", "SHA-256");
+        put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256");
+
+        put("MessageDigest.SHA-384", prefix + "OpenSSLMessageDigestJDK$SHA384");
+        put("Alg.Alias.MessageDigest.SHA384", "SHA-384");
+        put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.2", "SHA-384");
+
+        put("MessageDigest.SHA-512", prefix + "OpenSSLMessageDigestJDK$SHA512");
+        put("Alg.Alias.MessageDigest.SHA512", "SHA-512");
+        put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512");
+
+        // iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) md5(5)
+        put("MessageDigest.MD5", prefix + "OpenSSLMessageDigestJDK$MD5");
+        put("Alg.Alias.MessageDigest.1.2.840.113549.2.5", "MD5");
+
+        /* == KeyPairGenerators == */
+        put("KeyPairGenerator.RSA", prefix + "OpenSSLRSAKeyPairGenerator");
+        put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1.1", "RSA");
+
+        put("KeyPairGenerator.DSA", prefix + "OpenSSLDSAKeyPairGenerator");
+
+        put("KeyPairGenerator.EC", prefix + "OpenSSLECKeyPairGenerator");
+
+        /* == KeyFactory == */
+        put("KeyFactory.RSA", prefix + "OpenSSLRSAKeyFactory");
+        put("Alg.Alias.KeyFactory.1.2.840.113549.1.1.1", "RSA");
+
+        put("KeyFactory.DSA", prefix + "OpenSSLDSAKeyFactory");
+
+        put("KeyFactory.EC", prefix + "OpenSSLECKeyFactory");
+
+        /* == KeyAgreement == */
+        put("KeyAgreement.ECDH", prefix + "OpenSSLECDHKeyAgreement");
+
+        /* == Signatures == */
+        put("Signature.MD5WithRSA", prefix + "OpenSSLSignature$MD5RSA");
+        put("Alg.Alias.Signature.MD5WithRSAEncryption", "MD5WithRSA");
+        put("Alg.Alias.Signature.MD5/RSA", "MD5WithRSA");
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5WithRSA");
+        put("Alg.Alias.Signature.1.2.840.113549.2.5with1.2.840.113549.1.1.1", "MD5WithRSA");
+
+        put("Signature.SHA1WithRSA", prefix + "OpenSSLSignature$SHA1RSA");
+        put("Alg.Alias.Signature.SHA1WithRSAEncryption", "SHA1WithRSA");
+        put("Alg.Alias.Signature.SHA1/RSA", "SHA1WithRSA");
+        put("Alg.Alias.Signature.SHA-1/RSA", "SHA1WithRSA");
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1WithRSA");
+        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.1", "SHA1WithRSA");
+        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.5", "SHA1WithRSA");
+        put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1WithRSA");
+
+        put("Signature.SHA256WithRSA", prefix + "OpenSSLSignature$SHA256RSA");
+        put("Alg.Alias.Signature.SHA256WithRSAEncryption", "SHA256WithRSA");
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256WithRSA");
+        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.1",
+                "SHA256WithRSA");
+        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.11",
+                "SHA256WithRSA");
+
+        put("Signature.SHA384WithRSA", prefix + "OpenSSLSignature$SHA384RSA");
+        put("Alg.Alias.Signature.SHA384WithRSAEncryption", "SHA384WithRSA");
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384WithRSA");
+        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.113549.1.1.1",
+                "SHA384WithRSA");
+
+        put("Signature.SHA512WithRSA", prefix + "OpenSSLSignature$SHA512RSA");
+        put("Alg.Alias.Signature.SHA512WithRSAEncryption", "SHA512WithRSA");
+        put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512WithRSA");
+        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.113549.1.1.1",
+                "SHA512WithRSA");
+
+        put("Signature.SHA1withDSA", prefix + "OpenSSLSignature$SHA1DSA");
+        put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
+        put("Alg.Alias.Signature.DSA", "SHA1withDSA");
+        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.1", "SHA1withDSA");
+        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.3", "SHA1withDSA");
+        put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA");
+        put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
+
+        put("Signature.NONEwithRSA", prefix + "OpenSSLSignatureRawRSA");
+
+        put("Signature.ECDSA", prefix + "OpenSSLSignature$SHA1ECDSA");
+        put("Alg.Alias.Signature.SHA1withECDSA", "ECDSA");
+        put("Alg.Alias.Signature.ECDSAwithSHA1", "ECDSA");
+        // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA1(1)
+        put("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA");
+        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10045.2.1", "ECDSA");
+
+        // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA2(3)
+        put("Signature.SHA256withECDSA", prefix + "OpenSSLSignature$SHA256ECDSA");
+        // ecdsa-with-SHA256(2)
+        put("Alg.Alias.Signature.1.2.840.10045.4.3.2", "SHA256withECDSA");
+        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.10045.2.1", "SHA256withECDSA");
+
+        put("Signature.SHA384withECDSA", prefix + "OpenSSLSignature$SHA384ECDSA");
+        // ecdsa-with-SHA384(3)
+        put("Alg.Alias.Signature.1.2.840.10045.4.3.3", "SHA384withECDSA");
+        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.10045.2.1", "SHA384withECDSA");
+
+        put("Signature.SHA512withECDSA", prefix + "OpenSSLSignature$SHA512ECDSA");
+        // ecdsa-with-SHA512(4)
+        put("Alg.Alias.Signature.1.2.840.10045.4.3.4", "SHA512withECDSA");
+        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.10045.2.1", "SHA512withECDSA");
+
+        /* === SecureRandom === */
+        /*
+         * We have to specify SHA1PRNG because various documentation mentions
+         * that algorithm by name instead of just recommending calling
+         * "new SecureRandom()"
+         */
+        put("SecureRandom.SHA1PRNG", prefix + "OpenSSLRandom");
+        put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
+
+        /* === Cipher === */
+        put("Cipher.RSA/ECB/NoPadding", prefix + "OpenSSLCipherRSA$Raw");
+        put("Alg.Alias.Cipher.RSA/None/NoPadding", "RSA/ECB/NoPadding");
+        put("Cipher.RSA/ECB/PKCS1Padding", prefix + "OpenSSLCipherRSA$PKCS1");
+        put("Alg.Alias.Cipher.RSA/None/PKCS1Padding", "RSA/ECB/PKCS1Padding");
+
+        /*
+         * OpenSSL only supports a subset of modes, so we'll name them
+         * explicitly here.
+         */
+        put("Cipher.AES/ECB/NoPadding", prefix + "OpenSSLCipher$AES$ECB$NoPadding");
+        put("Cipher.AES/ECB/PKCS5Padding", prefix + "OpenSSLCipher$AES$ECB$PKCS5Padding");
+        put("Cipher.AES/CBC/NoPadding", prefix + "OpenSSLCipher$AES$CBC$NoPadding");
+        put("Cipher.AES/CBC/PKCS5Padding", prefix + "OpenSSLCipher$AES$CBC$PKCS5Padding");
+        put("Cipher.AES/CFB/NoPadding", prefix + "OpenSSLCipher$AES$CFB$NoPadding");
+        put("Cipher.AES/CFB/PKCS5Padding", prefix + "OpenSSLCipher$AES$CFB$PKCS5Padding");
+        put("Cipher.AES/CTR/NoPadding", prefix + "OpenSSLCipher$AES$CTR$NoPadding");
+        put("Cipher.AES/CTR/PKCS5Padding", prefix + "OpenSSLCipher$AES$CTR$PKCS5Padding");
+        put("Cipher.AES/OFB/NoPadding", prefix + "OpenSSLCipher$AES$OFB$NoPadding");
+        put("Cipher.AES/OFB/PKCS5Padding", prefix + "OpenSSLCipher$AES$OFB$PKCS5Padding");
+
+        put("Cipher.DESEDE/CBC/NoPadding", prefix + "OpenSSLCipher$DESEDE$CBC$NoPadding");
+        put("Cipher.DESEDE/CBC/PKCS5Padding", prefix + "OpenSSLCipher$DESEDE$CBC$PKCS5Padding");
+        put("Cipher.DESEDE/CFB/NoPadding", prefix + "OpenSSLCipher$DESEDE$CFB$NoPadding");
+        put("Cipher.DESEDE/CFB/PKCS5Padding", prefix + "OpenSSLCipher$DESEDE$CFB$PKCS5Padding");
+        put("Cipher.DESEDE/ECB/NoPadding", prefix + "OpenSSLCipher$DESEDE$ECB$NoPadding");
+        put("Cipher.DESEDE/ECB/PKCS5Padding", prefix + "OpenSSLCipher$DESEDE$ECB$PKCS5Padding");
+        put("Cipher.DESEDE/OFB/NoPadding", prefix + "OpenSSLCipher$DESEDE$OFB$NoPadding");
+        put("Cipher.DESEDE/OFB/PKCS5Padding", prefix + "OpenSSLCipher$DESEDE$OFB$PKCS5Padding");
+
+        put("Cipher.ARC4", prefix + "OpenSSLCipher$ARC4");
+
+        /* === Mac === */
+
+        put("Mac.HmacMD5", prefix + "OpenSSLMac$HmacMD5");
+
+        // PKCS#2 - iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2)
+        // http://www.oid-info.com/get/1.2.840.113549.2
+
+        // HMAC-SHA-1 PRF (7)
+        put("Mac.HmacSHA1", prefix + "OpenSSLMac$HmacSHA1");
+        put("Alg.Alias.Mac.1.2.840.113549.2.7", "HmacSHA1");
+        put("Alg.Alias.Mac.HMAC-SHA1", "HmacSHA1");
+        put("Alg.Alias.Mac.HMAC/SHA1", "HmacSHA1");
+
+        // id-hmacWithSHA256 (9)
+        put("Mac.HmacSHA256", prefix + "OpenSSLMac$HmacSHA256");
+        put("Alg.Alias.Mac.1.2.840.113549.2.9", "HmacSHA256");
+        put("Alg.Alias.Mac.HMAC-SHA256", "HmacSHA256");
+        put("Alg.Alias.Mac.HMAC/SHA256", "HmacSHA256");
+
+        // id-hmacWithSHA384 (10)
+        put("Mac.HmacSHA384", prefix + "OpenSSLMac$HmacSHA384");
+        put("Alg.Alias.Mac.1.2.840.113549.2.10", "HmacSHA384");
+        put("Alg.Alias.Mac.HMAC-SHA384", "HmacSHA384");
+        put("Alg.Alias.Mac.HMAC/SHA384", "HmacSHA384");
+
+        // id-hmacWithSHA384 (11)
+        put("Mac.HmacSHA512", prefix + "OpenSSLMac$HmacSHA512");
+        put("Alg.Alias.Mac.1.2.840.113549.2.11", "HmacSHA512");
+        put("Alg.Alias.Mac.HMAC-SHA512", "HmacSHA512");
+        put("Alg.Alias.Mac.HMAC/SHA512", "HmacSHA512");
+
+        /* === Certificate === */
+
+        put("CertificateFactory.X509", prefix + "OpenSSLX509CertificateFactory");
+        put("Alg.Alias.CertificateFactory.X.509", "X509");
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyFactory.java b/crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyFactory.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyFactory.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyFactory.java
index 9c61abd..c785ac6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyFactory.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyFactory.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.math.BigInteger;
 import java.security.InvalidKeyException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyPairGenerator.java b/crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyPairGenerator.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyPairGenerator.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyPairGenerator.java
index 2d19d4e..a00219f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyPairGenerator.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyPairGenerator.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.math.BigInteger;
 import java.security.InvalidAlgorithmParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateCrtKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateCrtKey.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateCrtKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateCrtKey.java
index c5254ad..1cbf5de 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateCrtKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateCrtKey.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateKey.java
index c0e0848..20db293 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateKey.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPublicKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPublicKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPublicKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRSAPublicKey.java
index 08b1920..4bbd7e3 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPublicKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPublicKey.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRandom.java b/crypto/src/main/java/org/conscrypt/OpenSSLRandom.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRandom.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRandom.java
index fd011f0..1683bb8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRandom.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRandom.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.Serializable;
 import java.security.SecureRandomSpi;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSecretKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLSecretKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSecretKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSecretKey.java
index 1bc59dc..193356e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSecretKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSecretKey.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLServerSocketFactoryImpl.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLServerSocketFactoryImpl.java
index c3cdaad..d14e921 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLServerSocketFactoryImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.net.InetAddress;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLServerSocketImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLServerSocketImpl.java
index 9744fe0..4c1f709 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLServerSocketImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.net.InetAddress;
@@ -233,7 +233,7 @@
                                + "to support the enabled cipher suites.");
     }
 
-    private boolean checkForPrivateKey(String keyType, Class keyClass) {
+    private boolean checkForPrivateKey(String keyType, Class<?> keyClass) {
         String alias = sslParameters.getKeyManager().chooseServerAlias(keyType, null, null);
         if (alias == null) {
             return false;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLSessionImpl.java
similarity index 94%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSessionImpl.java
index 1465027..3b7328d 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSessionImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.security.Principal;
@@ -193,9 +193,9 @@
      * @return an array of X509 certificates (the peer's one first and then
      *         eventually that of the certification authority) or null if no
      *         certificate were used during the SSL connection.
-     * @throws <code>SSLPeerUnverifiedCertificateException</code> if either a
-     *         not X509 certificate was used (i.e. Kerberos certificates) or the
-     *         peer could not be verified.
+     * @throws SSLPeerUnverifiedException if either a non-X.509 certificate
+     *         was used (i.e. Kerberos certificates) or the peer could not
+     *         be verified.
      */
     public javax.security.cert.X509Certificate[] getPeerCertificateChain()
             throws SSLPeerUnverifiedException {
@@ -240,9 +240,9 @@
      * @return an array of X509 certificates (the peer's one first and then
      *         eventually that of the certification authority) or null if no
      *         certificate were used during the SSL connection.
-     * @throws <code>SSLPeerUnverifiedException</code> if either a not X509
-     *         certificate was used (i.e. Kerberos certificates) or the peer
-     *         could not be verified.
+     * @throws SSLPeerUnverifiedException if either a non-X.509 certificate
+     *         was used (i.e. Kerberos certificates) or the peer could not
+     *         be verified.
      */
     public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
         checkPeerCertificatesPresent();
@@ -263,9 +263,8 @@
      * handshake phase is returned by this method.
      * @return a X500Principal of the last certificate for X509-based
      *         cipher suites.
-     * @throws <code>SSLPeerUnverifiedException</code> if either a not X509
-     *         certificate was used (i.e. Kerberos certificates) or the
-     *         peer does not exist.
+     * @throws SSLPeerUnverifiedException if either a non-X.509 certificate
+     *         was used (i.e. Kerberos certificates) or the peer does not exist.
      *
      */
     public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
@@ -371,7 +370,7 @@
      * @param name the name of the binding to find.
      * @return the value bound to that name, or null if the binding does not
      *         exist.
-     * @throws <code>IllegalArgumentException</code> if the argument is null.
+     * @throws IllegalArgumentException if the argument is null.
      */
     public Object getValue(String name) {
         if (name == null) {
@@ -401,8 +400,7 @@
      *            accepted!)
      * @param value data object that shall be bound to
      *            name.
-     * @throws <code>IllegalArgumentException</code> if one or both
-     *             argument(s) is null.
+     * @throws IllegalArgumentException if one or both argument(s) is null.
      */
     public void putValue(String name, Object value) {
         if (name == null || value == null) {
@@ -428,7 +426,7 @@
      *
      * @param name the name of the link (no null are
      *            accepted!)
-     * @throws <code>IllegalArgumentException</code> if the argument is null.
+     * @throws IllegalArgumentException if the argument is null.
      */
     public void removeValue(String name) {
         if (name == null) {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java b/crypto/src/main/java/org/conscrypt/OpenSSLSignature.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSignature.java
index 34115ea..8576010 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSignature.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.InvalidKeyException;
 import java.security.InvalidParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureRawRSA.java b/crypto/src/main/java/org/conscrypt/OpenSSLSignatureRawRSA.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureRawRSA.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSignatureRawRSA.java
index e5d33b3..9c4e4ad 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureRawRSA.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSignatureRawRSA.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.InvalidKeyException;
 import java.security.InvalidParameterException;
@@ -26,7 +26,6 @@
 import java.security.interfaces.RSAPrivateCrtKey;
 import java.security.interfaces.RSAPrivateKey;
 import java.security.interfaces.RSAPublicKey;
-import java.util.Arrays;
 
 /**
  * Implements the JDK Signature interface needed for RAW RSA signature
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLSocketFactoryImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSocketFactoryImpl.java
index 41c58b6..72fd89f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSocketFactoryImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.net.InetAddress;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLSocketImpl.java
similarity index 92%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSocketImpl.java
index ea56afb..7c5d78f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSocketImpl.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
@@ -25,6 +25,7 @@
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.SocketException;
+import java.security.InvalidKeyException;
 import java.security.PrivateKey;
 import java.security.SecureRandom;
 import java.security.cert.CertificateEncodingException;
@@ -48,7 +49,6 @@
 import libcore.io.Libcore;
 import libcore.io.Streams;
 import libcore.io.StructTimeval;
-import org.apache.harmony.security.provider.cert.X509CertImpl;
 
 /**
  * Implementation of the class OpenSSLSocketImpl based on OpenSSL.
@@ -72,6 +72,7 @@
     private final Object writeLock = new Object();
     private SSLParametersImpl sslParameters;
     private byte[] npnProtocols;
+    private byte[] alpnProtocols;
     private String[] enabledProtocols;
     private String[] enabledCipherSuites;
     private boolean useSessionTickets;
@@ -79,7 +80,7 @@
     /** Whether the TLS Channel ID extension is enabled. This field is server-side only. */
     private boolean channelIdEnabled;
     /** Private key for the TLS Channel ID extension. This field is client-side only. */
-    private PrivateKey channelIdPrivateKey;
+    private OpenSSLKey channelIdPrivateKey;
     private OpenSSLSessionImpl sslSession;
     private final Socket socket;
     private boolean autoClose;
@@ -280,6 +281,10 @@
                 NativeCrypto.SSL_CTX_enable_npn(sslCtxNativePointer);
             }
 
+            if (client && alpnProtocols != null) {
+                NativeCrypto.SSL_CTX_set_alpn_protos(sslCtxNativePointer, alpnProtocols);
+            }
+
             // setup server certificates and private keys.
             // clients will receive a call back to request certificates.
             if (!client) {
@@ -363,7 +368,7 @@
                     if (issuers != null && issuers.length != 0) {
                         byte[][] issuersBytes;
                         try {
-                            issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers);
+                            issuersBytes = encodeIssuerX509Principals(issuers);
                         } catch (CertificateEncodingException e) {
                             throw new IOException("Problem encoding principals", e);
                         }
@@ -381,14 +386,16 @@
             }
 
             // TLS Channel ID
-            if (client) {
-                // Client-side TLS Channel ID
-                if (channelIdPrivateKey != null) {
-                    NativeCrypto.SSL_set1_tls_channel_id(sslNativePointer, channelIdPrivateKey);
-                }
-            } else {
-                // Server-side TLS Channel ID
-                if (channelIdEnabled) {
+            if (channelIdEnabled) {
+                if (client) {
+                    // Client-side TLS Channel ID
+                    if (channelIdPrivateKey == null) {
+                        throw new SSLHandshakeException("Invalid TLS channel ID key specified");
+                    }
+                    NativeCrypto.SSL_set1_tls_channel_id(sslNativePointer,
+                            channelIdPrivateKey.getPkeyContext());
+                } else {
+                    // Server-side TLS Channel ID
                     NativeCrypto.SSL_enable_tls_channel_id(sslNativePointer);
                 }
             }
@@ -396,7 +403,8 @@
             int sslSessionNativePointer;
             try {
                 sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer,
-                        socket.getFileDescriptor$(), this, getSoTimeout(), client, npnProtocols);
+                        socket.getFileDescriptor$(), this, getSoTimeout(), client, npnProtocols,
+                        client ? null : alpnProtocols);
             } catch (CertificateException e) {
                 SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage());
                 wrapper.initCause(e);
@@ -446,6 +454,15 @@
         }
     }
 
+    private static byte[][] encodeIssuerX509Principals(X509Certificate[] certificates)
+            throws CertificateEncodingException {
+        byte[][] principalBytes = new byte[certificates.length][];
+        for (int i = 0; i < certificates.length; i++) {
+            principalBytes[i] = certificates[i].getIssuerX500Principal().getEncoded();
+        }
+        return principalBytes;
+    }
+
     String getPeerHostName() {
         if (wrappedHost != null) {
             return wrappedHost;
@@ -471,7 +488,7 @@
         }
         X509Certificate[] certificates = new X509Certificate[certificatesBytes.length];
         for (int i = 0; i < certificatesBytes.length; i++) {
-            certificates[i] = new X509CertImpl(certificatesBytes[i]);
+            certificates[i] = OpenSSLX509Certificate.fromX509Der(certificatesBytes[i]);
         }
         return certificates;
     }
@@ -489,14 +506,11 @@
             return;
         }
 
-        if (privateKey instanceof OpenSSLKeyHolder) {
-            OpenSSLKey key = ((OpenSSLKeyHolder) privateKey).getOpenSSLKey();
-            NativeCrypto.SSL_use_OpenSSL_PrivateKey(sslNativePointer, key.getPkeyContext());
-        } else if ("PKCS#8".equals(privateKey.getFormat())) {
-            byte[] privateKeyBytes = privateKey.getEncoded();
-            NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes);
-        } else {
-            throw new SSLException("Unsupported PrivateKey format: " + privateKey.getFormat());
+        try {
+            final OpenSSLKey key = OpenSSLKey.fromPrivateKey(privateKey);
+            NativeCrypto.SSL_use_PrivateKey(sslNativePointer, key.getPkeyContext());
+        } catch (InvalidKeyException e) {
+            throw new SSLException(e);
         }
 
         byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates);
@@ -585,7 +599,7 @@
             }
             X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length];
             for (int i = 0; i < bytes.length; i++) {
-                peerCertificateChain[i] = new X509CertImpl(bytes[i]);
+                peerCertificateChain[i] = OpenSSLX509Certificate.fromX509Der(bytes[i]);
             }
             boolean client = sslParameters.getUseClientMode();
             if (client) {
@@ -871,7 +885,17 @@
                     "Could not change Channel ID private key after the initial handshake has"
                     + " begun.");
         }
-        this.channelIdPrivateKey = privateKey;
+        if (privateKey == null) {
+            this.channelIdEnabled = false;
+            this.channelIdPrivateKey = null;
+        } else {
+            this.channelIdEnabled = true;
+            try {
+                this.channelIdPrivateKey = OpenSSLKey.fromPrivateKey(privateKey);
+            } catch (InvalidKeyException e) {
+                // Will have error in startHandshake
+            }
+        }
     }
 
     @Override public boolean getUseClientMode() {
@@ -1068,6 +1092,14 @@
     }
 
     /**
+     * Returns the protocol agreed upon by client and server, or {@code null} if
+     * no protocol was agreed upon.
+     */
+    public byte[] getAlpnSelectedProtocol() {
+        return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer);
+    }
+
+    /**
      * Sets the list of protocols this peer is interested in. If null no
      * protocols will be used.
      *
@@ -1082,4 +1114,21 @@
         }
         this.npnProtocols = npnProtocols;
     }
+
+    /**
+     * Sets the list of protocols this peer is interested in. If the list is
+     * {@code null}, no protocols will be used.
+     *
+     * @param alpnProtocols a non-empty array of protocol names. From
+     *            SSL_select_next_proto, "vector of 8-bit, length prefixed byte
+     *            strings. The length byte itself is not included in the length.
+     *            A byte string of length 0 is invalid. No byte string may be
+     *            truncated.".
+     */
+    public void setAlpnProtocols(byte[] alpnProtocols) {
+        if (alpnProtocols != null && alpnProtocols.length == 0) {
+            throw new IllegalArgumentException("alpnProtocols.length == 0");
+        }
+        this.alpnProtocols = alpnProtocols;
+    }
 }
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImplWrapper.java b/crypto/src/main/java/org/conscrypt/OpenSSLSocketImplWrapper.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImplWrapper.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSocketImplWrapper.java
index df65d12..b6f43fa 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImplWrapper.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSocketImplWrapper.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.net.InetAddress;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRL.java b/crypto/src/main/java/org/conscrypt/OpenSSLX509CRL.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRL.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLX509CRL.java
index 04418c7..56b99cc 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRL.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLX509CRL.java
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import org.apache.harmony.security.utils.AlgNameMapper;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLX509CertificateFactory.ParsingException;
-
+import org.conscrypt.OpenSSLX509CertificateFactory.ParsingException;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
@@ -43,7 +42,6 @@
 import java.util.List;
 import java.util.Set;
 import java.util.TimeZone;
-
 import javax.security.auth.x500.X500Principal;
 
 public class OpenSSLX509CRL extends X509CRL {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRLEntry.java b/crypto/src/main/java/org/conscrypt/OpenSSLX509CRLEntry.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRLEntry.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLX509CRLEntry.java
index 4965200..470cc98 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRLEntry.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLX509CRLEntry.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.ByteArrayOutputStream;
 import java.math.BigInteger;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertPath.java b/crypto/src/main/java/org/conscrypt/OpenSSLX509CertPath.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertPath.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLX509CertPath.java
index a96c361..57568b8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertPath.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLX509CertPath.java
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
-
-import org.apache.harmony.xnet.provider.jsse.OpenSSLX509CertificateFactory.ParsingException;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -31,6 +29,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import org.conscrypt.OpenSSLX509CertificateFactory.ParsingException;
 
 public class OpenSSLX509CertPath extends CertPath {
     private static final byte[] PKCS7_MARKER = "-----BEGIN PKCS7".getBytes();
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509Certificate.java b/crypto/src/main/java/org/conscrypt/OpenSSLX509Certificate.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509Certificate.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLX509Certificate.java
index daeb049..b1cd986 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509Certificate.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLX509Certificate.java
@@ -14,11 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
-
-import org.apache.harmony.security.utils.AlgNameMapper;
-import org.apache.harmony.security.x509.X509PublicKey;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLX509CertificateFactory.ParsingException;
+package org.conscrypt;
 
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
@@ -49,8 +45,9 @@
 import java.util.List;
 import java.util.Set;
 import java.util.TimeZone;
-
 import javax.security.auth.x500.X500Principal;
+import org.apache.harmony.security.utils.AlgNameMapper;
+import org.conscrypt.OpenSSLX509CertificateFactory.ParsingException;
 
 public class OpenSSLX509Certificate extends X509Certificate {
     private final long mContext;
@@ -61,6 +58,7 @@
 
     public static OpenSSLX509Certificate fromX509DerInputStream(InputStream is)
             throws ParsingException {
+        @SuppressWarnings("resource")
         final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
 
         try {
@@ -86,6 +84,7 @@
 
     public static List<OpenSSLX509Certificate> fromPkcs7DerInputStream(InputStream is)
             throws ParsingException {
+        @SuppressWarnings("resource")
         OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
 
         final long[] certRefs;
@@ -114,6 +113,7 @@
 
     public static OpenSSLX509Certificate fromX509PemInputStream(InputStream is)
             throws ParsingException {
+        @SuppressWarnings("resource")
         final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
 
         try {
@@ -131,6 +131,7 @@
 
     public static List<OpenSSLX509Certificate> fromPkcs7PemInputStream(InputStream is)
             throws ParsingException {
+        @SuppressWarnings("resource")
         OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
 
         final long[] certRefs;
@@ -412,7 +413,7 @@
          * We couldn't find anything else, so just return a nearly-unusable
          * X.509-encoded key.
          */
-        return new X509PublicKey(oid, encoded, null);
+        return new X509PublicKey(oid, encoded);
     }
 
     @Override
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertificateFactory.java b/crypto/src/main/java/org/conscrypt/OpenSSLX509CertificateFactory.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertificateFactory.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLX509CertificateFactory.java
index ca79785..75fdedb 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertificateFactory.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLX509CertificateFactory.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PRF.java b/crypto/src/main/java/org/conscrypt/PRF.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PRF.java
rename to crypto/src/main/java/org/conscrypt/PRF.java
index 6013d38..afbbb45 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PRF.java
+++ b/crypto/src/main/java/org/conscrypt/PRF.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.GeneralSecurityException;
 import java.security.MessageDigest;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java b/crypto/src/main/java/org/conscrypt/PinEntryException.java
similarity index 94%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java
rename to crypto/src/main/java/org/conscrypt/PinEntryException.java
index 8b74514..8c651db 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java
+++ b/crypto/src/main/java/org/conscrypt/PinEntryException.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 // public for testing by CertPinManagerTest
 public class PinEntryException extends Exception {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinFailureLogger.java b/crypto/src/main/java/org/conscrypt/PinFailureLogger.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinFailureLogger.java
rename to crypto/src/main/java/org/conscrypt/PinFailureLogger.java
index 40b1838..67bbc1f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinFailureLogger.java
+++ b/crypto/src/main/java/org/conscrypt/PinFailureLogger.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinListEntry.java b/crypto/src/main/java/org/conscrypt/PinListEntry.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinListEntry.java
rename to crypto/src/main/java/org/conscrypt/PinListEntry.java
index c05a391..a401700 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinListEntry.java
+++ b/crypto/src/main/java/org/conscrypt/PinListEntry.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.math.BigInteger;
 import java.security.MessageDigest;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinManagerException.java b/crypto/src/main/java/org/conscrypt/PinManagerException.java
similarity index 94%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinManagerException.java
rename to crypto/src/main/java/org/conscrypt/PinManagerException.java
index 74b3c65..e52ae83 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinManagerException.java
+++ b/crypto/src/main/java/org/conscrypt/PinManagerException.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 class PinManagerException extends Exception {
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ProtocolVersion.java b/crypto/src/main/java/org/conscrypt/ProtocolVersion.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ProtocolVersion.java
rename to crypto/src/main/java/org/conscrypt/ProtocolVersion.java
index 230f9fe..4e2555c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ProtocolVersion.java
+++ b/crypto/src/main/java/org/conscrypt/ProtocolVersion.java
@@ -14,7 +14,7 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.util.Hashtable;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLBufferedInput.java b/crypto/src/main/java/org/conscrypt/SSLBufferedInput.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLBufferedInput.java
rename to crypto/src/main/java/org/conscrypt/SSLBufferedInput.java
index c945dbb..d2834d3 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLBufferedInput.java
+++ b/crypto/src/main/java/org/conscrypt/SSLBufferedInput.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLClientSessionCache.java b/crypto/src/main/java/org/conscrypt/SSLClientSessionCache.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLClientSessionCache.java
rename to crypto/src/main/java/org/conscrypt/SSLClientSessionCache.java
index 8a73fa5..d070a02 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLClientSessionCache.java
+++ b/crypto/src/main/java/org/conscrypt/SSLClientSessionCache.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import javax.net.ssl.SSLSession;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java b/crypto/src/main/java/org/conscrypt/SSLContextImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLContextImpl.java
index 0e1e130..75aed4f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLContextImpl.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.security.GeneralSecurityException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineAppData.java b/crypto/src/main/java/org/conscrypt/SSLEngineAppData.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineAppData.java
rename to crypto/src/main/java/org/conscrypt/SSLEngineAppData.java
index b827016..f2cb77d 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineAppData.java
+++ b/crypto/src/main/java/org/conscrypt/SSLEngineAppData.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.nio.ByteBuffer;
 import javax.net.ssl.SSLException;
@@ -24,7 +24,7 @@
  * This class is used to retrieve the application data
  * arrived for the SSLEngine.
  */
-public class SSLEngineAppData implements org.apache.harmony.xnet.provider.jsse.Appendable {
+public class SSLEngineAppData implements Appendable {
 
     /**
      * Buffer containing received application data.
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineDataStream.java b/crypto/src/main/java/org/conscrypt/SSLEngineDataStream.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineDataStream.java
rename to crypto/src/main/java/org/conscrypt/SSLEngineDataStream.java
index e209dd1..f4a2d2d 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineDataStream.java
+++ b/crypto/src/main/java/org/conscrypt/SSLEngineDataStream.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.nio.ByteBuffer;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java b/crypto/src/main/java/org/conscrypt/SSLEngineImpl.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLEngineImpl.java
index 7f01c8a..3ed9980 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLEngineImpl.java
@@ -15,8 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
-
+package org.conscrypt;
 
 import java.io.IOException;
 import java.nio.BufferUnderflowException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java b/crypto/src/main/java/org/conscrypt/SSLInputStream.java
similarity index 92%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
rename to crypto/src/main/java/org/conscrypt/SSLInputStream.java
index 2a6c5d6..c8a5eca 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
+++ b/crypto/src/main/java/org/conscrypt/SSLInputStream.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -38,9 +38,9 @@
      * exception, not return -1. The type of exception depends
      * on implementation. It was done for simplifying and speeding
      * up of processing of such cases.
-     * @see org.apache.harmony.xnet.provider.jsse.SSLStreamedInput#read()
-     * @see org.apache.harmony.xnet.provider.jsse.SSLBufferedInput#read()
-     * @see org.apache.harmony.xnet.provider.jsse.HandshakeIODataStream#read()
+     * @see org.conscrypt.SSLStreamedInput#read()
+     * @see org.conscrypt.SSLBufferedInput#read()
+     * @see org.conscrypt.HandshakeIODataStream#read()
      */
     @Override
     public abstract int read() throws IOException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParametersImpl.java b/crypto/src/main/java/org/conscrypt/SSLParametersImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParametersImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLParametersImpl.java
index 287f9f3..21b8ae2 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParametersImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLParametersImpl.java
@@ -15,9 +15,8 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
-import org.apache.harmony.xnet.provider.jsse.TrustManagerImpl;
 import java.security.KeyManagementException;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLRecordProtocol.java b/crypto/src/main/java/org/conscrypt/SSLRecordProtocol.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLRecordProtocol.java
rename to crypto/src/main/java/org/conscrypt/SSLRecordProtocol.java
index e9f77f72..24b6c61 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLRecordProtocol.java
+++ b/crypto/src/main/java/org/conscrypt/SSLRecordProtocol.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import javax.net.ssl.SSLProtocolException;
@@ -82,7 +82,7 @@
     // alert protocol to indicate alerts occurred/received
     private AlertProtocol alertProtocol;
     // application data object to which application data will be transmitted
-    private org.apache.harmony.xnet.provider.jsse.Appendable appData;
+    private Appendable appData;
     // connection state holding object
     private ConnectionState
         activeReadState, activeWriteState, pendingConnectionState;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSessionCache.java b/crypto/src/main/java/org/conscrypt/SSLServerSessionCache.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSessionCache.java
rename to crypto/src/main/java/org/conscrypt/SSLServerSessionCache.java
index 32a0e72..a380ce9 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSessionCache.java
+++ b/crypto/src/main/java/org/conscrypt/SSLServerSessionCache.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import javax.net.ssl.SSLSession;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketFactoryImpl.java b/crypto/src/main/java/org/conscrypt/SSLServerSocketFactoryImpl.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLServerSocketFactoryImpl.java
index 22872f8..5b16f85 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLServerSocketFactoryImpl.java
@@ -15,14 +15,14 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.ServerSocket;
 import java.security.KeyManagementException;
 import javax.net.ssl.SSLServerSocketFactory;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
 
 /**
  * Implementation of SSLServerSocketFactory.
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketImpl.java b/crypto/src/main/java/org/conscrypt/SSLServerSocketImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLServerSocketImpl.java
index 477d03d..a30e3b4 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLServerSocketImpl.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.net.InetAddress;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java b/crypto/src/main/java/org/conscrypt/SSLSessionImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLSessionImpl.java
index 46834ad..9631b1e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSessionImpl.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.Principal;
 import java.security.SecureRandom;
@@ -29,7 +29,7 @@
 import javax.net.ssl.SSLSessionBindingEvent;
 import javax.net.ssl.SSLSessionBindingListener;
 import javax.net.ssl.SSLSessionContext;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
 
 public final class SSLSessionImpl implements SSLSession, Cloneable  {
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketFactoryImpl.java b/crypto/src/main/java/org/conscrypt/SSLSocketFactoryImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLSocketFactoryImpl.java
index 93496cf..dc971ac 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSocketFactoryImpl.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.net.InetAddress;
@@ -23,7 +23,7 @@
 import java.net.UnknownHostException;
 import java.security.KeyManagementException;
 import javax.net.ssl.SSLSocketFactory;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
 
 /**
  * Implementation of SSLSocketFactory.
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketImpl.java b/crypto/src/main/java/org/conscrypt/SSLSocketImpl.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLSocketImpl.java
index 3e72aeb..138a143 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSocketImpl.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketInputStream.java b/crypto/src/main/java/org/conscrypt/SSLSocketInputStream.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketInputStream.java
rename to crypto/src/main/java/org/conscrypt/SSLSocketInputStream.java
index 8016579..36c5c03 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketInputStream.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSocketInputStream.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -131,7 +131,7 @@
     // to this input stream.
     // It 'adapts' the InputStream interface to Appendable, which is used for
     // transmission of income data from the record protocol to its clients.
-    private class Adapter implements org.apache.harmony.xnet.provider.jsse.Appendable {
+    private class Adapter implements org.conscrypt.Appendable {
         /**
          * Appends the data to the stream.
          * This method could be implemented in the outer class
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketOutputStream.java b/crypto/src/main/java/org/conscrypt/SSLSocketOutputStream.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketOutputStream.java
rename to crypto/src/main/java/org/conscrypt/SSLSocketOutputStream.java
index 2666eee..e3afed7 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketOutputStream.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSocketOutputStream.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.OutputStream;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketWrapper.java b/crypto/src/main/java/org/conscrypt/SSLSocketWrapper.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketWrapper.java
rename to crypto/src/main/java/org/conscrypt/SSLSocketWrapper.java
index a393e24..2110aea 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketWrapper.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSocketWrapper.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLStreamedInput.java b/crypto/src/main/java/org/conscrypt/SSLStreamedInput.java
similarity index 91%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLStreamedInput.java
rename to crypto/src/main/java/org/conscrypt/SSLStreamedInput.java
index c040653..4c8a885 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLStreamedInput.java
+++ b/crypto/src/main/java/org/conscrypt/SSLStreamedInput.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -42,7 +42,7 @@
      * @return the value read from the underlying stream.
      * @throws IOException if the data could not be read from
      * the underlying stream
-     * @throws org.apache.harmony.xnet.provider.jsse.EndOfSourceException if the end of the underlying
+     * @throws org.conscrypt.EndOfSourceException if the end of the underlying
      * stream has been reached.
      */
     @Override
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLv3Constants.java b/crypto/src/main/java/org/conscrypt/SSLv3Constants.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLv3Constants.java
rename to crypto/src/main/java/org/conscrypt/SSLv3Constants.java
index 43dc178..ea6482f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLv3Constants.java
+++ b/crypto/src/main/java/org/conscrypt/SSLv3Constants.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 /**
  *
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java b/crypto/src/main/java/org/conscrypt/ServerHandshakeImpl.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
rename to crypto/src/main/java/org/conscrypt/ServerHandshakeImpl.java
index 29cb9cd..2e55c0d 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
+++ b/crypto/src/main/java/org/conscrypt/ServerHandshakeImpl.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.math.BigInteger;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHello.java b/crypto/src/main/java/org/conscrypt/ServerHello.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHello.java
rename to crypto/src/main/java/org/conscrypt/ServerHello.java
index 00a25f8..3cc3b46 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHello.java
+++ b/crypto/src/main/java/org/conscrypt/ServerHello.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.security.SecureRandom;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHelloDone.java b/crypto/src/main/java/org/conscrypt/ServerHelloDone.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHelloDone.java
rename to crypto/src/main/java/org/conscrypt/ServerHelloDone.java
index fd78b1f..3e40f9a 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHelloDone.java
+++ b/crypto/src/main/java/org/conscrypt/ServerHelloDone.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerKeyExchange.java b/crypto/src/main/java/org/conscrypt/ServerKeyExchange.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerKeyExchange.java
rename to crypto/src/main/java/org/conscrypt/ServerKeyExchange.java
index 7ccaf7cd3..d949850 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerKeyExchange.java
+++ b/crypto/src/main/java/org/conscrypt/ServerKeyExchange.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.math.BigInteger;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java b/crypto/src/main/java/org/conscrypt/ServerSessionContext.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
rename to crypto/src/main/java/org/conscrypt/ServerSessionContext.java
index f5716c1..8bd8b0f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
+++ b/crypto/src/main/java/org/conscrypt/ServerSessionContext.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import javax.net.ssl.SSLSession;
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerFactoryImpl.java b/crypto/src/main/java/org/conscrypt/TrustManagerFactoryImpl.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/TrustManagerFactoryImpl.java
index 159e362..150d018 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/TrustManagerFactoryImpl.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.IOException;
 import java.security.InvalidAlgorithmParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java b/crypto/src/main/java/org/conscrypt/TrustManagerImpl.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java
rename to crypto/src/main/java/org/conscrypt/TrustManagerImpl.java
index a5a1978..ef366d2 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java
+++ b/crypto/src/main/java/org/conscrypt/TrustManagerImpl.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.InvalidAlgorithmParameterException;
 import java.security.KeyStore;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateIndex.java b/crypto/src/main/java/org/conscrypt/TrustedCertificateIndex.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateIndex.java
rename to crypto/src/main/java/org/conscrypt/TrustedCertificateIndex.java
index 0b1f098..b322cd1 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateIndex.java
+++ b/crypto/src/main/java/org/conscrypt/TrustedCertificateIndex.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.PublicKey;
 import java.security.cert.CertPathValidatorException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateKeyStoreSpi.java b/crypto/src/main/java/org/conscrypt/TrustedCertificateKeyStoreSpi.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateKeyStoreSpi.java
rename to crypto/src/main/java/org/conscrypt/TrustedCertificateKeyStoreSpi.java
index 62a6647..c2d5c33 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateKeyStoreSpi.java
+++ b/crypto/src/main/java/org/conscrypt/TrustedCertificateKeyStoreSpi.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.InputStream;
 import java.io.OutputStream;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStore.java b/crypto/src/main/java/org/conscrypt/TrustedCertificateStore.java
similarity index 85%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStore.java
rename to crypto/src/main/java/org/conscrypt/TrustedCertificateStore.java
index e7b1a7c..1356776 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStore.java
+++ b/crypto/src/main/java/org/conscrypt/TrustedCertificateStore.java
@@ -14,13 +14,8 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
-import org.apache.harmony.security.x501.Name;
-import org.apache.harmony.security.x509.AuthorityKeyIdentifier;
-import org.apache.harmony.security.x509.GeneralName;
-import org.apache.harmony.security.x509.GeneralNames;
-import org.apache.harmony.security.x509.SubjectKeyIdentifier;
 import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -28,20 +23,17 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.math.BigInteger;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import javax.security.auth.x500.X500Principal;
 import libcore.io.IoUtils;
-import libcore.util.Objects;
 
 /**
  * A source for trusted root certificate authority (CA) certificates
@@ -380,107 +372,60 @@
         return null;
     }
 
-    private static AuthorityKeyIdentifier getAuthorityKeyIdentifier(X509Certificate cert) {
-        final byte[] akidBytes = cert.getExtensionValue("2.5.29.35");
-        if (akidBytes == null) {
+    private static boolean isSelfIssuedCertificate(OpenSSLX509Certificate cert) {
+        final long ctx = cert.getContext();
+        return NativeCrypto.X509_check_issued(ctx, ctx) == 0;
+    }
+
+    /**
+     * Converts the {@code cert} to the internal OpenSSL X.509 format so we can
+     * run {@link NativeCrypto} methods on it.
+     */
+    private static OpenSSLX509Certificate convertToOpenSSLIfNeeded(X509Certificate cert)
+            throws CertificateException {
+        if (cert == null) {
             return null;
         }
 
+        if (cert instanceof OpenSSLX509Certificate) {
+            return (OpenSSLX509Certificate) cert;
+        }
+
         try {
-            return AuthorityKeyIdentifier.decode(akidBytes);
-        } catch (IOException e) {
-            return null;
+            return OpenSSLX509Certificate.fromX509Der(cert.getEncoded());
+        } catch (Exception e) {
+            throw new CertificateException(e);
         }
     }
 
-    private static SubjectKeyIdentifier getSubjectKeyIdentifier(X509Certificate cert) {
-        final byte[] skidBytes = cert.getExtensionValue("2.5.29.14");
-        if (skidBytes == null) {
-            return null;
-        }
-
-        try {
-            return SubjectKeyIdentifier.decode(skidBytes);
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    private static boolean isSelfSignedCertificate(X509Certificate cert) {
-        if (!Objects.equal(cert.getSubjectX500Principal(), cert.getIssuerX500Principal())) {
-            return false;
-        }
-
-        final AuthorityKeyIdentifier akid = getAuthorityKeyIdentifier(cert);
-        if (akid != null) {
-            final byte[] akidKeyId = akid.getKeyIdentifier();
-            if (akidKeyId != null) {
-                final SubjectKeyIdentifier skid = getSubjectKeyIdentifier(cert);
-                if (!Arrays.equals(akidKeyId, skid.getKeyIdentifier())) {
-                    return false;
-                }
-            }
-
-            final BigInteger akidSerial = akid.getAuthorityCertSerialNumber();
-            if (akidSerial != null && !akidSerial.equals(cert.getSerialNumber())) {
-                return false;
-            }
-
-            final GeneralNames possibleIssuerNames = akid.getAuthorityCertIssuer();
-            if (possibleIssuerNames != null) {
-                GeneralName issuerName = null;
-
-                /* Get the first Directory Name (DN) to match how OpenSSL works. */
-                for (GeneralName possibleName : possibleIssuerNames.getNames()) {
-                    if (possibleName.getTag() == GeneralName.DIR_NAME) {
-                        issuerName = possibleName;
-                        break;
-                    }
-                }
-
-                if (issuerName != null) {
-                    final String issuerCanonical = ((Name) issuerName.getName())
-                            .getName(X500Principal.CANONICAL);
-
-                    try {
-                        final String subjectCanonical = new Name(cert.getSubjectX500Principal()
-                                .getEncoded()).getName(X500Principal.CANONICAL);
-                        if (!issuerCanonical.equals(subjectCanonical)) {
-                            return false;
-                        }
-                    } catch (IOException ignored) {
-                    }
-                }
-            }
-        }
-
-        return true;
-    }
-
     /**
      * Attempt to build a certificate chain from the supplied {@code leaf}
      * argument through the chain of issuers as high up as known. If the chain
      * can't be completed, the most complete chain available will be returned.
      * This means that a list with only the {@code leaf} certificate is returned
      * if no issuer certificates could be found.
+     *
+     * @throws CertificateException if there was a problem parsing the
+     *             certificates
      */
-    public List<X509Certificate> getCertificateChain(X509Certificate leaf) {
-        final List<X509Certificate> chain = new ArrayList<X509Certificate>();
-        chain.add(leaf);
+    public List<X509Certificate> getCertificateChain(X509Certificate leaf)
+            throws CertificateException {
+        final List<OpenSSLX509Certificate> chain = new ArrayList<OpenSSLX509Certificate>();
+        chain.add(convertToOpenSSLIfNeeded(leaf));
 
         for (int i = 0; true; i++) {
-            X509Certificate cert = chain.get(i);
-            if (isSelfSignedCertificate(cert)) {
+            OpenSSLX509Certificate cert = chain.get(i);
+            if (isSelfIssuedCertificate(cert)) {
                 break;
             }
-            X509Certificate issuer = findIssuer(cert);
+            OpenSSLX509Certificate issuer = convertToOpenSSLIfNeeded(findIssuer(cert));
             if (issuer == null) {
                 break;
             }
             chain.add(issuer);
         }
 
-        return chain;
+        return new ArrayList<X509Certificate>(chain);
     }
 
     // like java.security.cert.CertSelector but with X509Certificate and without cloning
diff --git a/crypto/src/main/java/org/conscrypt/X509PublicKey.java b/crypto/src/main/java/org/conscrypt/X509PublicKey.java
new file mode 100644
index 0000000..8d09fc2
--- /dev/null
+++ b/crypto/src/main/java/org/conscrypt/X509PublicKey.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 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.
+ */
+
+package org.conscrypt;
+
+import java.security.PublicKey;
+import java.util.Arrays;
+
+/**
+ * A simple but useless key class that holds X.509 public key information when
+ * the appropriate KeyFactory for the key algorithm is not available.
+ */
+public class X509PublicKey implements PublicKey {
+    private static final long serialVersionUID = -8610156854731664298L;
+
+    private final String algorithm;
+
+    private final byte[] encoded;
+
+    public X509PublicKey(String algorithm, byte[] encoded) {
+        this.algorithm = algorithm;
+        this.encoded = encoded;
+    }
+
+    @Override
+    public String getAlgorithm() {
+        return algorithm;
+    }
+
+    @Override
+    public String getFormat() {
+        return "X.509";
+    }
+
+    @Override
+    public byte[] getEncoded() {
+        return encoded;
+    }
+
+    @Override
+    public String toString() {
+        return "X509PublicKey [algorithm=" + algorithm + ", encoded=" + Arrays.toString(encoded)
+                + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((algorithm == null) ? 0 : algorithm.hashCode());
+        result = prime * result + Arrays.hashCode(encoded);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        X509PublicKey other = (X509PublicKey) obj;
+        if (algorithm == null) {
+            if (other.algorithm != null)
+                return false;
+        } else if (!algorithm.equals(other.algorithm))
+            return false;
+        if (!Arrays.equals(encoded, other.encoded))
+            return false;
+        return true;
+    }
+}
diff --git a/crypto/src/main/java/org/conscrypt/util/EmptyArray.java b/crypto/src/main/java/org/conscrypt/util/EmptyArray.java
new file mode 100644
index 0000000..e474562
--- /dev/null
+++ b/crypto/src/main/java/org/conscrypt/util/EmptyArray.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+// Copied from libcore.util.EmptyArray
+
+package org.conscrypt.util;
+
+public final class EmptyArray {
+    private EmptyArray() {}
+
+    public static final boolean[] BOOLEAN = new boolean[0];
+    public static final byte[] BYTE = new byte[0];
+    public static final char[] CHAR = new char[0];
+    public static final double[] DOUBLE = new double[0];
+    public static final int[] INT = new int[0];
+
+    public static final Class<?>[] CLASS = new Class[0];
+    public static final Object[] OBJECT = new Object[0];
+    public static final String[] STRING = new String[0];
+    public static final Throwable[] THROWABLE = new Throwable[0];
+    public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0];
+}
\ No newline at end of file
diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
similarity index 94%
rename from luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
rename to crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
index 6df0aa8..8a59fdc 100644
--- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
+++ b/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
@@ -15,9 +15,16 @@
  */
 
 /**
- * Native glue for Java class org.apache.harmony.xnet.provider.jsse.NativeCrypto
+ * Native glue for Java class org.conscrypt.NativeCrypto
  */
 
+#define TO_STRING1(x) #x
+#define TO_STRING(x) TO_STRING1(x)
+#ifndef JNI_JARJAR_PREFIX
+#define CONSCRYPT_UNBUNDLED
+#define JNI_JARJAR_PREFIX
+#endif
+
 #define LOG_TAG "NativeCrypto"
 
 #include <algorithm>
@@ -44,7 +51,6 @@
 #include "JniConstants.h"
 #include "JniException.h"
 #include "NetFd.h"
-#include "NetworkUtilities.h"
 #include "ScopedLocalRef.h"
 #include "ScopedPrimitiveArray.h"
 #include "ScopedUtfChars.h"
@@ -53,6 +59,21 @@
 #undef WITH_JNI_TRACE
 #undef WITH_JNI_TRACE_DATA
 
+/*
+ * How to use this for debugging with Wireshark:
+ *
+ * 1. Pull lines from logcat to a file that looks like (without quotes):
+ *     "RSA Session-ID:... Master-Key:..." <CR>
+ *     "RSA Session-ID:... Master-Key:..." <CR>
+ *     <etc>
+ * 2. Start Wireshark
+ * 3. Go to Edit -> Preferences -> SSL -> (Pre-)Master-Key log and fill in
+ *    the file you put the lines in above.
+ * 4. Follow the stream that corresponds to the desired "Session-ID" in
+ *    the Server Hello.
+ */
+#undef WITH_JNI_TRACE_KEYS
+
 #ifdef WITH_JNI_TRACE
 #define JNI_TRACE(...) \
         ((void)ALOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__));     \
@@ -70,6 +91,15 @@
 static JavaVM* gJavaVM;
 static jclass openSslOutputStreamClass;
 
+static jclass byteArrayClass;
+static jclass calendarClass;
+static jclass objectClass;
+static jclass objectArrayClass;
+static jclass integerClass;
+static jclass inputStreamClass;
+static jclass outputStreamClass;
+static jclass stringClass;
+
 static jmethodID calendar_setMethod;
 static jmethodID inputStream_readMethod;
 static jmethodID integer_valueOfMethod;
@@ -317,6 +347,13 @@
 }
 
 /**
+ * Throws a OutOfMemoryError with the given string as a message.
+ */
+static void jniThrowOutOfMemory(JNIEnv* env, const char* message) {
+    jniThrowException(env, "java/lang/OutOfMemoryError", message);
+}
+
+/**
  * Throws a BadPaddingException with the given string as a message.
  */
 static void throwBadPaddingException(JNIEnv* env, const char* message) {
@@ -1040,6 +1077,25 @@
 };
 
 /**
+ * Copied from libnativehelper NetworkUtilites.cpp
+ */
+static bool setBlocking(int fd, bool blocking) {
+    int flags = fcntl(fd, F_GETFL);
+    if (flags == -1) {
+        return false;
+    }
+
+    if (!blocking) {
+        flags |= O_NONBLOCK;
+    } else {
+        flags &= ~O_NONBLOCK;
+    }
+
+    int rc = fcntl(fd, F_SETFL, flags);
+    return (rc != -1);
+}
+
+/**
  * OpenSSL locking support. Taken from the O'Reilly book by Viega et al., but I
  * suppose there are not many other ways to do this on a Linux system (modulo
  * isomorphism).
@@ -1582,7 +1638,7 @@
 
     Unique_BIO buffer(BIO_new(BIO_s_mem()));
     if (buffer.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate BIO");
+        jniThrowOutOfMemory(env, "Unable to allocate BIO");
         return NULL;
     }
 
@@ -1612,7 +1668,7 @@
 
     Unique_BIO buffer(BIO_new(BIO_s_mem()));
     if (buffer.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate BIO");
+        jniThrowOutOfMemory(env, "Unable to allocate BIO");
         return NULL;
     }
 
@@ -1760,7 +1816,7 @@
 
     Unique_RSA rsa(RSA_new());
     if (rsa.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate RSA key");
+        jniThrowOutOfMemory(env, "Unable to allocate RSA key");
         return 0;
     }
 
@@ -1875,7 +1931,7 @@
         return 0;
     }
 
-    jobjectArray joa = env->NewObjectArray(2, JniConstants::byteArrayClass, NULL);
+    jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL);
     if (joa == NULL) {
         return NULL;
     }
@@ -1913,7 +1969,7 @@
         return 0;
     }
 
-    jobjectArray joa = env->NewObjectArray(8, JniConstants::byteArrayClass, NULL);
+    jobjectArray joa = env->NewObjectArray(8, byteArrayClass, NULL);
     if (joa == NULL) {
         return NULL;
     }
@@ -2008,7 +2064,7 @@
     Unique_DSA dsa(DSA_new());
     if (dsa.get() == NULL) {
         JNI_TRACE("DSA_generate_key failed");
-        jniThrowOutOfMemoryError(env, "Unable to allocate DSA key");
+        jniThrowOutOfMemory(env, "Unable to allocate DSA key");
         freeOpenSslErrorState();
         return 0;
     }
@@ -2075,7 +2131,7 @@
         return 0;
     }
 
-    jobjectArray joa = env->NewObjectArray(5, JniConstants::byteArrayClass, NULL);
+    jobjectArray joa = env->NewObjectArray(5, byteArrayClass, NULL);
     if (joa == NULL) {
         return NULL;
     }
@@ -2309,7 +2365,7 @@
         return NULL;
     }
 
-    jobjectArray joa = env->NewObjectArray(3, JniConstants::byteArrayClass, NULL);
+    jobjectArray joa = env->NewObjectArray(3, byteArrayClass, NULL);
     if (joa == NULL) {
         return NULL;
     }
@@ -2344,7 +2400,7 @@
     Unique_BIGNUM order(BN_new());
     if (order.get() == NULL) {
         JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
-        jniThrowOutOfMemoryError(env, "BN_new");
+        jniThrowOutOfMemory(env, "BN_new");
         return NULL;
     }
 
@@ -2387,7 +2443,7 @@
     Unique_BIGNUM cofactor(BN_new());
     if (cofactor.get() == NULL) {
         JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
-        jniThrowOutOfMemoryError(env, "BN_new");
+        jniThrowOutOfMemory(env, "BN_new");
         return NULL;
     }
 
@@ -2503,7 +2559,7 @@
     Unique_EC_POINT dup(EC_POINT_dup(generator, group));
     if (dup.get() == NULL) {
         JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
-        jniThrowOutOfMemoryError(env, "unable to dupe generator");
+        jniThrowOutOfMemory(env, "unable to dupe generator");
         return 0;
     }
 
@@ -2524,7 +2580,7 @@
 
     EC_POINT* point = EC_POINT_new(group);
     if (point == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable create an EC_POINT");
+        jniThrowOutOfMemory(env, "Unable create an EC_POINT");
         return 0;
     }
 
@@ -2641,7 +2697,7 @@
         return NULL;
     }
 
-    jobjectArray joa = env->NewObjectArray(2, JniConstants::byteArrayClass, NULL);
+    jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL);
     if (joa == NULL) {
         return NULL;
     }
@@ -2670,7 +2726,7 @@
     Unique_EC_KEY eckey(EC_KEY_new());
     if (eckey.get() == NULL) {
         JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
-        jniThrowOutOfMemoryError(env, "Unable to create an EC_KEY");
+        jniThrowOutOfMemory(env, "Unable to create an EC_KEY");
         return 0;
     }
 
@@ -2830,7 +2886,7 @@
 
     Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
     if (ctx.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable create a EVP_MD_CTX");
+        jniThrowOutOfMemory(env, "Unable create a EVP_MD_CTX");
         return 0;
     }
 
@@ -2867,7 +2923,7 @@
 
     EVP_MD_CTX* copy = EVP_MD_CTX_create();
     if (copy == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate copy of EVP_MD_CTX");
+        jniThrowOutOfMemory(env, "Unable to allocate copy of EVP_MD_CTX");
         return 0;
     }
 
@@ -2928,7 +2984,7 @@
 
     Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
     if (ctx.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate EVP_MD_CTX");
+        jniThrowOutOfMemory(env, "Unable to allocate EVP_MD_CTX");
         return 0;
     }
     JNI_TRACE("NativeCrypto_EVP_DigestInit ctx=%p", ctx.get());
@@ -3148,7 +3204,7 @@
 
     Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
     if (ctx.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate EVP_MD_CTX");
+        jniThrowOutOfMemory(env, "Unable to allocate EVP_MD_CTX");
         return 0;
     }
     JNI_TRACE("NativeCrypto_EVP_SignInit ctx=%p", ctx.get());
@@ -3249,7 +3305,7 @@
 
     Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
     if (ctx.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate EVP_MD_CTX");
+        jniThrowOutOfMemory(env, "Unable to allocate EVP_MD_CTX");
         return 0;
     }
     JNI_TRACE("NativeCrypto_EVP_VerifyInit ctx=%p", ctx.get());
@@ -3514,7 +3570,7 @@
 
     Unique_EVP_CIPHER_CTX ctx(EVP_CIPHER_CTX_new());
     if (ctx.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate cipher context");
+        jniThrowOutOfMemory(env, "Unable to allocate cipher context");
         JNI_TRACE("EVP_CipherInit_ex => context allocation error");
         return 0;
     }
@@ -3741,7 +3797,7 @@
 
     UniquePtr<unsigned char[]> buffer(new unsigned char[outputSize]);
     if (buffer.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate buffer for read");
+        jniThrowOutOfMemory(env, "Unable to allocate buffer for read");
         return 0;
     }
 
@@ -3783,7 +3839,7 @@
 
     UniquePtr<unsigned char[]> buffer(new unsigned char[length]);
     if (buffer.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate buffer for write");
+        jniThrowOutOfMemory(env, "Unable to allocate buffer for write");
         return;
     }
 
@@ -3815,7 +3871,7 @@
 
     Unique_BIO buffer(BIO_new(BIO_s_mem()));
     if (buffer.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate BIO");
+        jniThrowOutOfMemory(env, "Unable to allocate BIO");
         JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
         return NULL;
     }
@@ -3939,8 +3995,7 @@
      */
     const int origCount = count;
 
-    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count,
-            JniConstants::objectArrayClass, NULL));
+    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, objectArrayClass, NULL));
     for (int i = 0, j = 0; i < origCount; i++, j++) {
         GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack, i);
         ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
@@ -3960,10 +4015,9 @@
             continue;
         }
 
-        ScopedLocalRef<jobjectArray> item(env, env->NewObjectArray(2, JniConstants::objectClass,
-                NULL));
+        ScopedLocalRef<jobjectArray> item(env, env->NewObjectArray(2, objectClass, NULL));
 
-        ScopedLocalRef<jobject> type(env, env->CallStaticObjectMethod(JniConstants::integerClass,
+        ScopedLocalRef<jobject> type(env, env->CallStaticObjectMethod(integerClass,
                 integer_valueOfMethod, gen->type));
         env->SetObjectArrayElement(item.get(), 0, type.get());
         env->SetObjectArrayElement(item.get(), 1, val.get());
@@ -3979,8 +4033,8 @@
         JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type,
                 origCount, count);
 
-        ScopedLocalRef<jobjectArray> joa_copy(env, env->NewObjectArray(count,
-                JniConstants::objectArrayClass, NULL));
+        ScopedLocalRef<jobjectArray> joa_copy(env, env->NewObjectArray(count, objectArrayClass,
+                NULL));
 
         for (int i = 0; i < count; i++) {
             ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
@@ -4125,6 +4179,16 @@
     return x509->ex_flags;
 }
 
+static jboolean NativeCrypto_X509_check_issued(JNIEnv*, jclass, jlong x509Ref1, jlong x509Ref2) {
+    X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
+    X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
+    JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
+
+    int ret = X509_check_issued(x509_1, x509_2);
+    JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
+    return ret;
+}
+
 static void get_X509_signature(X509 *x509, ASN1_BIT_STRING** signature) {
     *signature = x509->signature;
 }
@@ -5168,8 +5232,7 @@
     }
 
     size_t size = sk_ASN1_OBJECT_num(objArray.get());
-    ScopedLocalRef<jobjectArray> exKeyUsage(env, env->NewObjectArray(size,
-            JniConstants::stringClass, NULL));
+    ScopedLocalRef<jobjectArray> exKeyUsage(env, env->NewObjectArray(size, stringClass, NULL));
     if (exKeyUsage.get() == NULL) {
         return NULL;
     }
@@ -5243,7 +5306,7 @@
 
     JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
 
-    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, JniConstants::stringClass, NULL));
+    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, stringClass, NULL));
     if (joa.get() == NULL) {
         JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
         return NULL;
@@ -5357,7 +5420,7 @@
         return NULL;
     }
 
-    jobjectArray joa = env->NewObjectArray(count, JniConstants::byteArrayClass, NULL);
+    jobjectArray joa = env->NewObjectArray(count, byteArrayClass, NULL);
     if (joa == NULL) {
         return NULL;
     }
@@ -5389,8 +5452,7 @@
         return NULL;
     }
 
-    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, JniConstants::byteArrayClass,
-            NULL));
+    ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, byteArrayClass, NULL));
     if (joa.get() == NULL) {
         return NULL;
     }
@@ -5496,6 +5558,9 @@
     jbyteArray npnProtocolsArray;
     jbyte* npnProtocolsData;
     size_t npnProtocolsLength;
+    jbyteArray alpnProtocolsArray;
+    jbyte* alpnProtocolsData;
+    size_t alpnProtocolsLength;
     Unique_RSA ephemeralRsa;
     Unique_EC_KEY ephemeralEc;
 
@@ -5540,6 +5605,9 @@
             npnProtocolsArray(NULL),
             npnProtocolsData(NULL),
             npnProtocolsLength(-1),
+            alpnProtocolsArray(NULL),
+            alpnProtocolsData(NULL),
+            alpnProtocolsLength(-1),
             ephemeralRsa(NULL),
             ephemeralEc(NULL) {
         fdsEmergency[0] = -1;
@@ -5558,8 +5626,12 @@
      * @param npnProtocols NPN protocols so that they may be advertised (by the
      *                     server) or selected (by the client). Has no effect
      *                     unless NPN is enabled.
+     * @param alpnProtocols ALPN protocols so that they may be advertised (by the
+     *                     server) or selected (by the client). Passing non-NULL
+     *                     enables ALPN.
      */
-    bool setCallbackState(JNIEnv* e, jobject shc, jobject fd, jbyteArray npnProtocols) {
+    bool setCallbackState(JNIEnv* e, jobject shc, jobject fd, jbyteArray npnProtocols,
+            jbyteArray alpnProtocols) {
         NetFd netFd(e, fd);
         if (netFd.isClosed()) {
             return false;
@@ -5575,6 +5647,14 @@
                 return false;
             }
         }
+        if (alpnProtocols != NULL) {
+            alpnProtocolsArray = alpnProtocols;
+            alpnProtocolsLength = e->GetArrayLength(alpnProtocols);
+            alpnProtocolsData = e->GetByteArrayElements(alpnProtocols, NULL);
+            if (alpnProtocolsData == NULL) {
+                return false;
+            }
+        }
         return true;
     }
 
@@ -5587,6 +5667,12 @@
             npnProtocolsData = NULL;
             npnProtocolsLength = -1;
         }
+        if (alpnProtocolsArray != NULL) {
+            env->ReleaseByteArrayElements(alpnProtocolsArray, alpnProtocolsData, JNI_ABORT);
+            alpnProtocolsArray = NULL;
+            alpnProtocolsData = NULL;
+            alpnProtocolsLength = -1;
+        }
         env = NULL;
     }
 
@@ -5883,6 +5969,9 @@
         *x509Out = certificate;
         *pkeyOut = privatekey;
         result = 1;
+    } else {
+        // Some error conditions return NULL, so make sure it doesn't linger.
+        freeOpenSslErrorState();
     }
     JNI_TRACE("ssl=%p client_cert_cb => *x509=%p *pkey=%p %d", ssl, *x509Out, *pkeyOut, result);
     return result;
@@ -6178,18 +6267,19 @@
     return javaBytes;
 }
 
-static void NativeCrypto_SSL_use_OpenSSL_PrivateKey_for_tls_channel_id(
-        JNIEnv* env, jclass, jlong ssl_address, jlong pkeyRef)
+static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass,
+        jlong ssl_address, jlong pkeyRef)
 {
     SSL* ssl = to_SSL(env, ssl_address, true);
     EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_OpenSSL_PrivateKey_for_tls_channel_id privatekey=%p",
-            ssl, pkey);
+    JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkey);
     if (ssl == NULL) {
         return;
     }
 
     if (pkey == NULL) {
+        jniThrowNullPointerException(env, "pkey == null");
+        JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
         return;
     }
 
@@ -6204,86 +6294,28 @@
         throwSSLExceptionWithSslErrors(
                 env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
         SSL_clear(ssl);
-        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_OpenSSL_PrivateKey_for_tls_channel_id => error", ssl);
+        JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
         return;
     }
-    // SSL_use_PrivateKey expects to take ownership of the EVP_PKEY,
-    // but we have an external reference from the caller such as an
-    // OpenSSLKey, so we manually increment the reference count here.
+    // SSL_set1_tls_channel_id expects to take ownership of the EVP_PKEY, but
+    // we have an external reference from the caller such as an OpenSSLKey,
+    // so we manually increment the reference count here.
     CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
 
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_OpenSSL_PrivateKey_for_tls_channel_id => ok", ssl);
+    JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
 }
 
-static void NativeCrypto_SSL_use_PKCS8_PrivateKey_for_tls_channel_id(
-        JNIEnv* env, jclass, jlong ssl_address, jbyteArray privatekey)
-{
-    SSL* ssl = to_SSL(env, ssl_address, true);
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id privatekey=%p", ssl,
-            privatekey);
-    if (ssl == NULL) {
-        return;
-    }
-
-    ScopedByteArrayRO buf(env, privatekey);
-    if (buf.get() == NULL) {
-        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id => threw exception",
-                ssl);
-        return;
-    }
-    const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
-    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &tmp, buf.size()));
-    if (pkcs8.get() == NULL) {
-        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
-        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
-                                       "Error parsing private key from DER to PKCS8");
-        SSL_clear(ssl);
-        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error from DER to PKCS8", ssl);
-        return;
-    }
-
-    Unique_EVP_PKEY privatekeyevp(EVP_PKCS82PKEY(pkcs8.get()));
-    if (privatekeyevp.get() == NULL) {
-        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
-        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
-                                       "Error creating private key from PKCS8");
-        SSL_clear(ssl);
-        JNI_TRACE(
-                "ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id => error from PKCS8 to key",
-                ssl);
-        return;
-    }
-
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id EVP_PKEY_type=%d",
-              ssl, EVP_PKEY_type(privatekeyevp.get()->type));
-
-    // SSL_set1_tls_channel_id requires ssl->server to be set to 0.
-    // Unfortunately, the default value is 1 and it's only changed to 0 just
-    // before the handshake starts (see NativeCrypto_SSL_do_handshake).
-    ssl->server = 0;
-    long ret = SSL_set1_tls_channel_id(ssl, privatekeyevp.get());
-    if (ret == 1L) {
-        OWNERSHIP_TRANSFERRED(privatekeyevp);
-    } else {
-        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
-        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
-        SSL_clear(ssl);
-        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id => error", ssl);
-        return;
-    }
-
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id => ok", ssl);
-}
-
-static void NativeCrypto_SSL_use_OpenSSL_PrivateKey(JNIEnv* env, jclass, jlong ssl_address, jlong pkeyRef) {
+static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, jlong ssl_address, jlong pkeyRef) {
     SSL* ssl = to_SSL(env, ssl_address, true);
     EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
-    JNI_TRACE("ssl=%p SSL_use_OpenSSL_PrivateKey privatekey=%p", ssl, pkey);
+    JNI_TRACE("ssl=%p SSL_use_PrivateKey privatekey=%p", ssl, pkey);
     if (ssl == NULL) {
         return;
     }
 
     if (pkey == NULL) {
+        jniThrowNullPointerException(env, "pkey == null");
+        JNI_TRACE("ssl=%p SSL_use_PrivateKey => pkey == null", ssl);
         return;
     }
 
@@ -6292,7 +6324,7 @@
         ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
         throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
         SSL_clear(ssl);
-        JNI_TRACE("ssl=%p SSL_use_OpenSSL_PrivateKey => error", ssl);
+        JNI_TRACE("ssl=%p SSL_use_PrivateKey => error", ssl);
         return;
     }
     // SSL_use_PrivateKey expects to take ownership of the EVP_PKEY,
@@ -6300,58 +6332,7 @@
     // OpenSSLKey, so we manually increment the reference count here.
     CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
 
-    JNI_TRACE("ssl=%p SSL_use_OpenSSL_PrivateKey => ok", ssl);
-}
-
-static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass,
-                                            jlong ssl_address, jbyteArray privatekey)
-{
-    SSL* ssl = to_SSL(env, ssl_address, true);
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey privatekey=%p", ssl, privatekey);
-    if (ssl == NULL) {
-        return;
-    }
-
-    ScopedByteArrayRO buf(env, privatekey);
-    if (buf.get() == NULL) {
-        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => threw exception", ssl);
-        return;
-    }
-    const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
-    Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &tmp, buf.size()));
-    if (pkcs8.get() == NULL) {
-        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
-        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
-                                       "Error parsing private key from DER to PKCS8");
-        SSL_clear(ssl);
-        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error from DER to PKCS8", ssl);
-        return;
-    }
-
-    Unique_EVP_PKEY privatekeyevp(EVP_PKCS82PKEY(pkcs8.get()));
-    if (privatekeyevp.get() == NULL) {
-        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
-        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
-                                       "Error creating private key from PKCS8");
-        SSL_clear(ssl);
-        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error from PKCS8 to key", ssl);
-        return;
-    }
-
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey EVP_PKEY_type=%d",
-              ssl, EVP_PKEY_type(privatekeyevp.get()->type));
-    int ret = SSL_use_PrivateKey(ssl, privatekeyevp.get());
-    if (ret == 1) {
-        OWNERSHIP_TRANSFERRED(privatekeyevp);
-    } else {
-        ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
-        throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
-        SSL_clear(ssl);
-        JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error", ssl);
-        return;
-    }
-
-    JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => ok", ssl);
+    JNI_TRACE("ssl=%p SSL_use_PrivateKey => ok", ssl);
 }
 
 static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass,
@@ -6416,13 +6397,13 @@
 
     Unique_sk_X509 chain(sk_X509_new_null());
     if (chain.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate local certificate chain");
+        jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
         JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
         return;
     }
     for (int i = 1; i < length; i++) {
         if (!sk_X509_push(chain.get(), certificatesX509.release(i))) {
-            jniThrowOutOfMemoryError(env, "Unable to push certificate");
+            jniThrowOutOfMemory(env, "Unable to push certificate");
             JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificate push error", ssl);
             return;
         }
@@ -6481,7 +6462,7 @@
 
     Unique_sk_X509_NAME principalsStack(sk_X509_NAME_new_null());
     if (principalsStack.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate principal stack");
+        jniThrowOutOfMemory(env, "Unable to allocate principal stack");
         JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
         return;
     }
@@ -6512,7 +6493,7 @@
         }
 
         if (!sk_X509_NAME_push(principalsStack.get(), principalX509Name.release())) {
-            jniThrowOutOfMemoryError(env, "Unable to push principal");
+            jniThrowOutOfMemory(env, "Unable to push principal");
             JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
             return;
         }
@@ -6652,7 +6633,7 @@
             if ((strcmp(c.c_str(), cipher->name) == 0)
                     && (strcmp(SSL_CIPHER_get_version(cipher), "SSLv2"))) {
                 if (!sk_SSL_CIPHER_push(cipherstack.get(), cipher)) {
-                    jniThrowOutOfMemoryError(env, "Unable to push cipher");
+                    jniThrowOutOfMemory(env, "Unable to push cipher");
                     JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists => cipher push error", ssl);
                     return;
                 }
@@ -6771,36 +6752,69 @@
 }
 
 /**
- * Callback for the client to select a protocol.
+ * A common selection path for both NPN and ALPN since they're essentially the
+ * same protocol. The list of protocols in "primary" is considered the order
+ * which should take precedence.
  */
-static int next_proto_select_callback(SSL* ssl, unsigned char **out, unsigned char *outlen,
-        const unsigned char *in, unsigned int inlen, void *)
+static int proto_select(SSL* ssl __attribute__ ((unused)),
+        unsigned char **out, unsigned char *outLength,
+        const unsigned char *primary, const unsigned int primaryLength,
+        const unsigned char *secondary, const unsigned int secondaryLength) {
+    if (primary != NULL) {
+        JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
+
+        int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
+                secondaryLength);
+        switch (status) {
+        case OPENSSL_NPN_NEGOTIATED:
+            JNI_TRACE("ssl=%p proto_select NPN/ALPN negotiated", ssl);
+            break;
+        case OPENSSL_NPN_UNSUPPORTED:
+            JNI_TRACE("ssl=%p proto_select NPN/ALPN unsupported", ssl);
+            break;
+        case OPENSSL_NPN_NO_OVERLAP:
+            JNI_TRACE("ssl=%p proto_select NPN/ALPN no overlap", ssl);
+            break;
+        }
+    } else {
+        JNI_TRACE("protocols=NULL");
+    }
+    return SSL_TLSEXT_ERR_OK;
+}
+
+/**
+ * Callback for the server to select an ALPN protocol.
+ */
+static int alpn_select_callback(SSL* ssl, const unsigned char **out, unsigned char *outlen,
+        const unsigned char *in, unsigned int inlen, void *) {
+    JNI_TRACE("ssl=%p alpn_select_callback", ssl);
+
+    AppData* appData = toAppData(ssl);
+    JNI_TRACE("AppData=%p", appData);
+
+    return proto_select(ssl, const_cast<unsigned char **>(out), outlen,
+            reinterpret_cast<unsigned char*>(appData->alpnProtocolsData),
+            appData->alpnProtocolsLength, in, inlen);
+}
+
+/**
+ * Callback for the client to select an NPN protocol.
+ */
+static int next_proto_select_callback(SSL* ssl, unsigned char** out, unsigned char* outlen,
+                                      const unsigned char* in, unsigned int inlen, void*)
 {
     JNI_TRACE("ssl=%p next_proto_select_callback", ssl);
 
+    AppData* appData = toAppData(ssl);
+    JNI_TRACE("AppData=%p", appData);
+
     // Enable False Start on the client if the server understands NPN
     // http://www.imperialviolet.org/2012/04/11/falsestart.html
     SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
 
-    AppData* appData = toAppData(ssl);
-    JNI_TRACE("AppData=%p", appData);
-    unsigned char* npnProtocols = reinterpret_cast<unsigned char*>(appData->npnProtocolsData);
-    size_t npnProtocolsLength = appData->npnProtocolsLength;
-    JNI_TRACE("npn_protocols=%p, length=%d", npnProtocols, npnProtocolsLength);
-
-    int status = SSL_select_next_proto(out, outlen, in, inlen, npnProtocols, npnProtocolsLength);
-    switch (status) {
-      case OPENSSL_NPN_NEGOTIATED:
-        JNI_TRACE("ssl=%p next_proto_select_callback NPN negotiated", ssl);
-        break;
-      case OPENSSL_NPN_UNSUPPORTED:
-        JNI_TRACE("ssl=%p next_proto_select_callback NPN unsupported", ssl);
-        break;
-      case OPENSSL_NPN_NO_OVERLAP:
-        JNI_TRACE("ssl=%p next_proto_select_callback NPN no overlap", ssl);
-        break;
-    }
-    return SSL_TLSEXT_ERR_OK;
+    return proto_select(ssl, out, outlen, in, inlen,
+            reinterpret_cast<unsigned char*>(appData->npnProtocolsData),
+            appData->npnProtocolsLength);
 }
 
 /**
@@ -6860,13 +6874,120 @@
     return result;
 }
 
+static int NativeCrypto_SSL_CTX_set_alpn_protos(JNIEnv* env, jclass, jlong ssl_ctx_address,
+        jbyteArray protos) {
+    SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
+    if (ssl_ctx == NULL) {
+        return 0;
+    }
+
+    JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=%p", ssl_ctx, protos);
+
+    if (protos == NULL) {
+        JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=NULL", ssl_ctx);
+        return 1;
+    }
+
+    ScopedByteArrayRO protosBytes(env, protos);
+    if (protosBytes.get() == NULL) {
+        JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=%p => protosBytes == NULL", ssl_ctx,
+                protos);
+        return 0;
+    }
+
+    const unsigned char *tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
+    int ret = SSL_CTX_set_alpn_protos(ssl_ctx, tmp, protosBytes.size());
+    JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=%p => ret=%d", ssl_ctx, protos, ret);
+    return ret;
+}
+
+static jbyteArray NativeCrypto_SSL_get0_alpn_selected(JNIEnv* env, jclass,
+        jlong ssl_address)
+{
+    SSL* ssl = to_SSL(env, ssl_address, true);
+    JNI_TRACE("ssl=%p SSL_get0_alpn_selected", ssl);
+    if (ssl == NULL) {
+        return NULL;
+    }
+    const jbyte* npn;
+    unsigned npnLength;
+    SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
+    if (npnLength == 0) {
+        return NULL;
+    }
+    jbyteArray result = env->NewByteArray(npnLength);
+    if (result != NULL) {
+        env->SetByteArrayRegion(result, 0, npnLength, npn);
+    }
+    return result;
+}
+
+#ifdef WITH_JNI_TRACE_KEYS
+static inline char hex_char(unsigned char in)
+{
+    if (in < 10) {
+        return '0' + in;
+    } else if (in <= 0xF0) {
+        return 'A' + in - 10;
+    } else {
+        return '?';
+    }
+}
+
+static void hex_string(char **dest, unsigned char* input, int len)
+{
+    *dest = (char*) malloc(len * 2 + 1);
+    char *output = *dest;
+    for (int i = 0; i < len; i++) {
+        *output++ = hex_char(input[i] >> 4);
+        *output++ = hex_char(input[i] & 0xF);
+    }
+    *output = '\0';
+}
+
+static void debug_print_session_key(SSL_SESSION* session)
+{
+    char *session_id_str;
+    char *master_key_str;
+    const char *key_type;
+    char *keyline;
+
+    hex_string(&session_id_str, session->session_id, session->session_id_length);
+    hex_string(&master_key_str, session->master_key, session->master_key_length);
+
+    X509* peer = SSL_SESSION_get0_peer(session);
+    EVP_PKEY* pkey = X509_PUBKEY_get(peer->cert_info->key);
+    switch (EVP_PKEY_type(pkey->type)) {
+    case EVP_PKEY_RSA:
+        key_type = "RSA";
+        break;
+    case EVP_PKEY_DSA:
+        key_type = "DSA";
+        break;
+    case EVP_PKEY_EC:
+        key_type = "EC";
+        break;
+    default:
+        key_type = "Unknown";
+        break;
+    }
+
+    asprintf(&keyline, "%s Session-ID:%s Master-Key:%s\n", key_type, session_id_str,
+            master_key_str);
+    JNI_TRACE("ssl_session=%p %s", session, keyline);
+
+    free(session_id_str);
+    free(master_key_str);
+    free(keyline);
+}
+#endif /* WITH_JNI_TRACE_KEYS */
+
 /**
  * Perform SSL handshake
  */
-static jlong NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
-        jobject fdObject, jobject shc, jint timeout_millis, jboolean client_mode,
-        jbyteArray npnProtocols)
-{
+static jlong NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
+        jobject shc, jint timeout_millis, jboolean client_mode, jbyteArray npnProtocols,
+        jbyteArray alpnProtocols) {
     SSL* ssl = to_SSL(env, ssl_address, true);
     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d client_mode=%d npn=%p",
               ssl, fdObject, shc, timeout_millis, client_mode, npnProtocols);
@@ -6932,13 +7053,16 @@
         SSL_set_connect_state(ssl);
     } else {
         SSL_set_accept_state(ssl);
+        if (alpnProtocols != NULL) {
+            SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
+        }
     }
 
     ret = 0;
     while (appData->aliveAndKicking) {
         errno = 0;
 
-        if (!appData->setCallbackState(env, shc, fdObject, npnProtocols)) {
+        if (!appData->setCallbackState(env, shc, fdObject, npnProtocols, alpnProtocols)) {
             // SocketException thrown by NetFd.isClosed
             SSL_clear(ssl);
             JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => 0", ssl);
@@ -7034,6 +7158,9 @@
     }
     SSL_SESSION* ssl_session = SSL_get1_session(ssl);
     JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => ssl_session=%p", ssl, ssl_session);
+#ifdef WITH_JNI_TRACE_KEYS
+    debug_print_session_key(ssl_session);
+#endif
     return (jlong) ssl_session;
 }
 
@@ -7079,24 +7206,26 @@
     X509* certificate = SSL_get_certificate(ssl);
     if (certificate == NULL) {
         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
+        // SSL_get_certificate can return NULL during an error as well.
+        freeOpenSslErrorState();
         return NULL;
     }
 
     Unique_sk_X509 chain(sk_X509_new_null());
     if (chain.get() == NULL) {
-        jniThrowOutOfMemoryError(env, "Unable to allocate local certificate chain");
+        jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => threw exception", ssl);
         return NULL;
     }
     if (!sk_X509_push(chain.get(), certificate)) {
-        jniThrowOutOfMemoryError(env, "Unable to push local certificate");
+        jniThrowOutOfMemory(env, "Unable to push local certificate");
         JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
         return NULL;
     }
     STACK_OF(X509)* cert_chain = SSL_get_certificate_chain(ssl, certificate);
     for (int i=0; i<sk_X509_num(cert_chain); i++) {
         if (!sk_X509_push(chain.get(), sk_X509_value(cert_chain, i))) {
-            jniThrowOutOfMemoryError(env, "Unable to push local certificate chain");
+            jniThrowOutOfMemory(env, "Unable to push local certificate chain");
             JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
             return NULL;
         }
@@ -7125,12 +7254,12 @@
         }
         chain_copy.reset(sk_X509_dup(chain));
         if (chain_copy.get() == NULL) {
-            jniThrowOutOfMemoryError(env, "Unable to allocate peer certificate chain");
+            jniThrowOutOfMemory(env, "Unable to allocate peer certificate chain");
             JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate dup error", ssl);
             return NULL;
         }
         if (!sk_X509_push(chain_copy.get(), x509)) {
-            jniThrowOutOfMemoryError(env, "Unable to push server's peer certificate");
+            jniThrowOutOfMemory(env, "Unable to push server's peer certificate");
             JNI_TRACE("ssl=%p NativeCrypto_SSL_get_peer_cert_chain => certificate push error", ssl);
             return NULL;
         }
@@ -7178,7 +7307,7 @@
 
         unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
 
-        if (!appData->setCallbackState(env, shc, fdObject, NULL)) {
+        if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
             MUTEX_UNLOCK(appData->mutex);
             return THROWN_EXCEPTION;
         }
@@ -7199,7 +7328,7 @@
 #ifdef WITH_JNI_TRACE_DATA
         for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
             int n = std::min(result - i, WITH_JNI_TRACE_DATA_CHUNK_SIZE);
-            JNI_TRACE("ssl=%p sslRead data: %d:\n%*s", ssl, n, n, buf+i);
+            JNI_TRACE("ssl=%p sslRead data: %d:\n%.*s", ssl, n, n, buf+i);
         }
 #endif
 
@@ -7380,7 +7509,7 @@
 
         unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
 
-        if (!appData->setCallbackState(env, shc, fdObject, NULL)) {
+        if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
             MUTEX_UNLOCK(appData->mutex);
             return THROWN_EXCEPTION;
         }
@@ -7403,7 +7532,7 @@
 #ifdef WITH_JNI_TRACE_DATA
         for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
             int n = std::min(result - i, WITH_JNI_TRACE_DATA_CHUNK_SIZE);
-            JNI_TRACE("ssl=%p sslWrite data: %d:\n%*s", ssl, n, n, buf+i);
+            JNI_TRACE("ssl=%p sslWrite data: %d:\n%.*s", ssl, n, n, buf+i);
         }
 #endif
 
@@ -7585,7 +7714,7 @@
 
     AppData* appData = toAppData(ssl);
     if (appData != NULL) {
-        if (!appData->setCallbackState(env, shc, fdObject, NULL)) {
+        if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
             // SocketException thrown by NetFd.isClosed
             SSL_clear(ssl);
             freeOpenSslErrorState();
@@ -7747,6 +7876,9 @@
 static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
     SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
     JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
+    if (ssl_session == NULL) {
+        return NULL;
+    }
     return ASN1ToByteArray<SSL_SESSION, i2d_SSL_SESSION>(env, ssl_session);
 }
 
@@ -7792,7 +7924,7 @@
 }
 
 #define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
-#define SSL_CALLBACKS "Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$SSLHandshakeCallbacks;"
+#define SSL_CALLBACKS "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
 static JNINativeMethod sNativeCryptoMethods[] = {
     NATIVE_METHOD(NativeCrypto, clinit, "()V"),
     NATIVE_METHOD(NativeCrypto, ENGINE_load_dynamic, "()V"),
@@ -7889,7 +8021,7 @@
     NATIVE_METHOD(NativeCrypto, OBJ_txt2nid, "(Ljava/lang/String;)I"),
     NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_longName, "(Ljava/lang/String;)Ljava/lang/String;"),
     NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_oid, "(Ljava/lang/String;)Ljava/lang/String;"),
-    NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, "(Lorg/apache/harmony/xnet/provider/jsse/OpenSSLBIOInputStream;)J"),
+    NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, ("(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;)J")),
     NATIVE_METHOD(NativeCrypto, create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
     NATIVE_METHOD(NativeCrypto, BIO_read, "(J[B)I"),
     NATIVE_METHOD(NativeCrypto, BIO_write, "(J[BII)V"),
@@ -7943,6 +8075,7 @@
     NATIVE_METHOD(NativeCrypto, get_X509_signature, "(J)[B"),
     NATIVE_METHOD(NativeCrypto, get_X509_CRL_signature, "(J)[B"),
     NATIVE_METHOD(NativeCrypto, get_X509_ex_flags, "(J)I"),
+    NATIVE_METHOD(NativeCrypto, X509_check_issued, "(JJ)I"),
     NATIVE_METHOD(NativeCrypto, d2i_X509_CRL_bio, "(J)J"),
     NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509_CRL, "(J)J"),
     NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_cert, "(JJ)J"),
@@ -7967,10 +8100,8 @@
     NATIVE_METHOD(NativeCrypto, SSL_new, "(J)J"),
     NATIVE_METHOD(NativeCrypto, SSL_enable_tls_channel_id, "(J)V"),
     NATIVE_METHOD(NativeCrypto, SSL_get_tls_channel_id, "(J)[B"),
-    NATIVE_METHOD(NativeCrypto, SSL_use_OpenSSL_PrivateKey_for_tls_channel_id, "(JJ)V"),
-    NATIVE_METHOD(NativeCrypto, SSL_use_PKCS8_PrivateKey_for_tls_channel_id, "(J[B)V"),
-    NATIVE_METHOD(NativeCrypto, SSL_use_OpenSSL_PrivateKey, "(JJ)V"),
-    NATIVE_METHOD(NativeCrypto, SSL_use_PrivateKey, "(J[B)V"),
+    NATIVE_METHOD(NativeCrypto, SSL_set1_tls_channel_id, "(JJ)V"),
+    NATIVE_METHOD(NativeCrypto, SSL_use_PrivateKey, "(JJ)V"),
     NATIVE_METHOD(NativeCrypto, SSL_use_certificate, "(J[[B)V"),
     NATIVE_METHOD(NativeCrypto, SSL_check_private_key, "(J)V"),
     NATIVE_METHOD(NativeCrypto, SSL_set_client_CA_list, "(J[[B)V"),
@@ -7986,7 +8117,7 @@
     NATIVE_METHOD(NativeCrypto, SSL_set_session_creation_enabled, "(JZ)V"),
     NATIVE_METHOD(NativeCrypto, SSL_set_tlsext_host_name, "(JLjava/lang/String;)V"),
     NATIVE_METHOD(NativeCrypto, SSL_get_servername, "(J)Ljava/lang/String;"),
-    NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "IZ[B)I"),
+    NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "IZ[B[B)I"),
     NATIVE_METHOD(NativeCrypto, SSL_renegotiate, "(J)V"),
     NATIVE_METHOD(NativeCrypto, SSL_get_certificate, "(J)[[B"),
     NATIVE_METHOD(NativeCrypto, SSL_get_peer_cert_chain, "(J)[[B"),
@@ -8005,30 +8136,86 @@
     NATIVE_METHOD(NativeCrypto, SSL_CTX_enable_npn, "(J)V"),
     NATIVE_METHOD(NativeCrypto, SSL_CTX_disable_npn, "(J)V"),
     NATIVE_METHOD(NativeCrypto, SSL_get_npn_negotiated_protocol, "(J)[B"),
+    NATIVE_METHOD(NativeCrypto, SSL_CTX_set_alpn_protos, "(J[B)I"),
+    NATIVE_METHOD(NativeCrypto, SSL_get0_alpn_selected, "(J)[B"),
     NATIVE_METHOD(NativeCrypto, ERR_peek_last_error, "()J"),
 };
 
-void register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(JNIEnv* env) {
-    JNI_TRACE("register_org_apache_harmony_xnet_provider_jsse_NativeCrypto");
-    jniRegisterNativeMethods(env, "org/apache/harmony/xnet/provider/jsse/NativeCrypto",
+static void initialize_conscrypt(JNIEnv* env) {
+    jniRegisterNativeMethods(env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto",
                              sNativeCryptoMethods, NELEM(sNativeCryptoMethods));
 
-    env->GetJavaVM(&gJavaVM);
-
     ScopedLocalRef<jclass> localClass(env,
-            env->FindClass("org/apache/harmony/xnet/provider/jsse/OpenSSLBIOInputStream"));
+            env->FindClass(TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream"));
     openSslOutputStreamClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
     if (openSslOutputStreamClass == NULL) {
         ALOGE("failed to find class OpenSSLBIOInputStream");
         abort();
     }
 
-    calendar_setMethod = env->GetMethodID(JniConstants::calendarClass, "set", "(IIIIII)V");
-    inputStream_readMethod = env->GetMethodID(JniConstants::inputStreamClass, "read", "([B)I");
-    integer_valueOfMethod = env->GetStaticMethodID(JniConstants::integerClass, "valueOf",
+    calendar_setMethod = env->GetMethodID(calendarClass, "set", "(IIIIII)V");
+    inputStream_readMethod = env->GetMethodID(inputStreamClass, "read", "([B)I");
+    integer_valueOfMethod = env->GetStaticMethodID(integerClass, "valueOf",
             "(I)Ljava/lang/Integer;");
     openSslInputStream_readLineMethod = env->GetMethodID(openSslOutputStreamClass, "gets",
             "([B)I");
-    outputStream_writeMethod = env->GetMethodID(JniConstants::outputStreamClass, "write", "([B)V");
-    outputStream_flushMethod = env->GetMethodID(JniConstants::outputStreamClass, "flush", "()V");
+    outputStream_writeMethod = env->GetMethodID(outputStreamClass, "write", "([B)V");
+    outputStream_flushMethod = env->GetMethodID(outputStreamClass, "flush", "()V");
 }
+
+#if defined(CONSCRYPT_UNBUNDLED)
+
+static jclass findClass(JNIEnv* env, const char* name) {
+    ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
+    jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
+    if (result == NULL) {
+        ALOGE("failed to find class '%s'", name);
+        abort();
+    }
+    return result;
+}
+
+// Use JNI_OnLoad for when we're standalone
+int JNI_OnLoad(JavaVM *vm, void* reserved) {
+    JNI_TRACE("JNI_OnLoad NativeCrypto");
+    gJavaVM = vm;
+
+    JNIEnv *env;
+    if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
+        ALOGE("Could not get JNIEnv");
+        return JNI_ERR;
+    }
+
+    byteArrayClass = findClass(env, "[B");
+    calendarClass = findClass(env, "java/util/Calendar");
+    inputStreamClass = findClass(env, "java/io/InputStream");
+    integerClass = findClass(env, "java/lang/Integer");
+    objectClass = findClass(env, "java/lang/Object");
+    objectArrayClass = findClass(env, "[Ljava/lang/Object;");
+    outputStreamClass = findClass(env, "java/io/OutputStream");
+    stringClass = findClass(env, "java/lang/String");
+
+    initialize_conscrypt(env);
+    return JNI_VERSION_1_6;
+}
+
+#else
+
+// Use this when built into Android
+void register_org_conscrypt_NativeCrypto(JNIEnv* env) {
+    JNI_TRACE("register_org_conscrypt_NativeCrypto");
+
+    byteArrayClass = JniConstants::byteArrayClass;
+    calendarClass = JniConstants::calendarClass;
+    inputStreamClass = JniConstants::inputStreamClass;
+    integerClass = JniConstants::integerClass;
+    objectClass = JniConstants::objectClass;
+    objectArrayClass = JniConstants::objectArrayClass;
+    outputStreamClass = JniConstants::outputStreamClass;
+    stringClass = JniConstants::stringClass;
+
+    env->GetJavaVM(&gJavaVM);
+    initialize_conscrypt(env);
+}
+
+#endif // defined(CONSCRYPT_UNBUNDLED)
diff --git a/crypto/src/main/native/sub.mk b/crypto/src/main/native/sub.mk
new file mode 100644
index 0000000..62f8672
--- /dev/null
+++ b/crypto/src/main/native/sub.mk
@@ -0,0 +1,18 @@
+# -*- mode: makefile -*-
+# This file is included by the top-level libcore Android.mk.
+# It's not a normal makefile, so we don't include CLEAR_VARS
+# or BUILD_*_LIBRARY.
+
+LOCAL_SRC_FILES := \
+	org_conscrypt_NativeCrypto.cpp
+
+LOCAL_C_INCLUDES += \
+	libcore/luni/src/main/native
+
+# Any shared/static libs that are listed here must also
+# be listed in libs/nativehelper/Android.mk.
+# TODO: fix this requirement
+
+#LOCAL_SHARED_LIBRARIES +=
+
+#LOCAL_STATIC_LIBRARIES +=
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CertPinManagerTest.java b/crypto/src/test/java/org/conscrypt/CertPinManagerTest.java
similarity index 98%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CertPinManagerTest.java
rename to crypto/src/test/java/org/conscrypt/CertPinManagerTest.java
index 8359c99..04890f6 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CertPinManagerTest.java
+++ b/crypto/src/test/java/org/conscrypt/CertPinManagerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.File;
 import java.io.FileWriter;
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzerTest.java b/crypto/src/test/java/org/conscrypt/ChainStrengthAnalyzerTest.java
similarity index 98%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzerTest.java
rename to crypto/src/test/java/org/conscrypt/ChainStrengthAnalyzerTest.java
index 42585b9..7663789 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzerTest.java
+++ b/crypto/src/test/java/org/conscrypt/ChainStrengthAnalyzerTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
@@ -125,4 +125,4 @@
         InputStream pemInput = new ByteArrayInputStream(pem.getBytes());
         return (X509Certificate) cf.generateCertificate(pemInput);
     }
-}
\ No newline at end of file
+}
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java b/crypto/src/test/java/org/conscrypt/CipherSuiteTest.java
similarity index 97%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java
rename to crypto/src/test/java/org/conscrypt/CipherSuiteTest.java
index 7adecaf..970ad34 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java
+++ b/crypto/src/test/java/org/conscrypt/CipherSuiteTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.MessageDigest;
 import java.util.ArrayList;
@@ -24,7 +24,6 @@
 import javax.crypto.Mac;
 import junit.framework.TestCase;
 import libcore.java.security.StandardNames;
-import org.apache.harmony.xnet.provider.jsse.CipherSuite;
 
 public class CipherSuiteTest extends TestCase {
     public void test_getByName() throws Exception {
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContextTest.java b/crypto/src/test/java/org/conscrypt/ClientSessionContextTest.java
similarity index 98%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContextTest.java
rename to crypto/src/test/java/org/conscrypt/ClientSessionContextTest.java
index 6d17a25..93037db 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContextTest.java
+++ b/crypto/src/test/java/org/conscrypt/ClientSessionContextTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.util.Enumeration;
 import java.util.HashSet;
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCacheTest.java b/crypto/src/test/java/org/conscrypt/FileClientSessionCacheTest.java
similarity index 97%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCacheTest.java
rename to crypto/src/test/java/org/conscrypt/FileClientSessionCacheTest.java
index 9714cc3..9d7e2ec 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCacheTest.java
+++ b/crypto/src/test/java/org/conscrypt/FileClientSessionCacheTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/crypto/src/test/java/org/conscrypt/MacTest.java b/crypto/src/test/java/org/conscrypt/MacTest.java
new file mode 100644
index 0000000..304ecdb
--- /dev/null
+++ b/crypto/src/test/java/org/conscrypt/MacTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.conscrypt;
+
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import junit.framework.TestCase;
+
+public class MacTest extends TestCase {
+    public void test_getInstance_OpenSSL_ENGINE() throws Exception {
+        final String secret = "-HMAC-test1";
+        final byte[] testString = "testing123".getBytes();
+
+        Provider p = Security.getProvider(OpenSSLProvider.PROVIDER_NAME);
+        NativeCryptoTest.loadTestEngine();
+        OpenSSLEngine engine = OpenSSLEngine.getInstance(NativeCryptoTest.TEST_ENGINE_ID);
+
+        /*
+         * The "-HMAC-" prefix is a special prefix recognized by
+         * test_openssl_engine.cpp
+         */
+        SecretKey key1 = engine.getSecretKeyById(secret, "HmacSHA256");
+        SecretKey key1dupe = engine.getSecretKeyById(secret, "HmacSHA256");
+
+        /* Non-ENGINE-based SecretKey */
+        SecretKey key2 = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
+
+        /* The one that is ENGINE-based can't be equal to a non-ENGINE one. */
+        assertFalse(key1.equals(key2));
+        assertEquals(key1, key1dupe);
+        assertNull(key1.getFormat());
+        assertNull(key1.getEncoded());
+        assertEquals("RAW", key2.getFormat());
+        assertEquals(Arrays.toString(secret.getBytes()), Arrays.toString(key2.getEncoded()));
+
+        Mac mac1 = Mac.getInstance("HmacSHA256", p);
+        mac1.init(key1);
+        mac1.update(testString);
+        byte[] output1 = mac1.doFinal();
+        assertEquals(mac1.getMacLength(), output1.length);
+
+        Mac mac2 = Mac.getInstance("HmacSHA256", p);
+        mac2.init(key2);
+        mac2.update(testString);
+        byte[] output2 = mac2.doFinal();
+
+        assertEquals(Arrays.toString(output2), Arrays.toString(output1));
+    }
+}
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java b/crypto/src/test/java/org/conscrypt/NativeCryptoTest.java
similarity index 94%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java
rename to crypto/src/test/java/org/conscrypt/NativeCryptoTest.java
index f456f3e..8692f8a 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java
+++ b/crypto/src/test/java/org/conscrypt/NativeCryptoTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import dalvik.system.BaseDexClassLoader;
 import java.io.ByteArrayInputStream;
@@ -29,7 +29,6 @@
 import java.security.KeyPairGenerator;
 import java.security.KeyStore;
 import java.security.KeyStore.PrivateKeyEntry;
-import java.security.PrivateKey;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.security.interfaces.DSAPublicKey;
@@ -53,8 +52,8 @@
 import libcore.io.IoUtils;
 import libcore.java.security.StandardNames;
 import libcore.java.security.TestKeyStore;
-import org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSLHandshakeCallbacks;
-import static org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH;
+import org.conscrypt.NativeCrypto.SSLHandshakeCallbacks;
+import static org.conscrypt.NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH;
 
 public class NativeCryptoTest extends TestCase {
     /** Corresponds to the native test library "libjavacoretests.so" */
@@ -67,12 +66,12 @@
 
     private static final long TIMEOUT_SECONDS = 5;
 
-    private static byte[] SERVER_PRIVATE_KEY;
+    private static OpenSSLKey SERVER_PRIVATE_KEY;
     private static byte[][] SERVER_CERTIFICATES;
-    private static byte[] CLIENT_PRIVATE_KEY;
+    private static OpenSSLKey CLIENT_PRIVATE_KEY;
     private static byte[][] CLIENT_CERTIFICATES;
     private static byte[][] CA_PRINCIPALS;
-    private static PrivateKey CHANNEL_ID_PRIVATE_KEY;
+    private static OpenSSLKey CHANNEL_ID_PRIVATE_KEY;
     private static byte[] CHANNEL_ID;
 
     @Override
@@ -80,7 +79,7 @@
         assertEquals(0, NativeCrypto.ERR_peek_last_error());
     }
 
-    private static byte[] getServerPrivateKey() {
+    private static OpenSSLKey getServerPrivateKey() {
         initCerts();
         return SERVER_PRIVATE_KEY;
     }
@@ -90,7 +89,7 @@
         return SERVER_CERTIFICATES;
     }
 
-    private static byte[] getClientPrivateKey() {
+    private static OpenSSLKey getClientPrivateKey() {
         initCerts();
         return CLIENT_PRIVATE_KEY;
     }
@@ -116,13 +115,13 @@
         try {
             PrivateKeyEntry serverPrivateKeyEntry
                     = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
-            SERVER_PRIVATE_KEY = serverPrivateKeyEntry.getPrivateKey().getEncoded();
+            SERVER_PRIVATE_KEY = OpenSSLKey.fromPrivateKey(serverPrivateKeyEntry.getPrivateKey());
             SERVER_CERTIFICATES = NativeCrypto.encodeCertificates(
                     serverPrivateKeyEntry.getCertificateChain());
 
             PrivateKeyEntry clientPrivateKeyEntry
                     = TestKeyStore.getClientCertificate().getPrivateKey("RSA", "RSA");
-            CLIENT_PRIVATE_KEY = clientPrivateKeyEntry.getPrivateKey().getEncoded();
+            CLIENT_PRIVATE_KEY = OpenSSLKey.fromPrivateKey(clientPrivateKeyEntry.getPrivateKey());
             CLIENT_CERTIFICATES = NativeCrypto.encodeCertificates(
                     clientPrivateKeyEntry.getCertificateChain());
 
@@ -147,7 +146,7 @@
         BigInteger s = new BigInteger(
                 "229cdbbf489aea584828a261a23f9ff8b0f66f7ccac98bf2096ab3aee41497c5", 16);
         CHANNEL_ID_PRIVATE_KEY = new OpenSSLECPrivateKey(
-                new ECPrivateKeySpec(s, openSslSpec.getECParameterSpec()));
+                new ECPrivateKeySpec(s, openSslSpec.getECParameterSpec())).getOpenSSLKey();
 
         // Channel ID is the concatenation of the X and Y coordinates of the public key.
         CHANNEL_ID = new BigInteger(
@@ -339,7 +338,7 @@
 
     public void test_SSL_use_PrivateKey_for_tls_channel_id() throws Exception {
         try {
-            NativeCrypto.SSL_set1_tls_channel_id(NULL, null);
+            NativeCrypto.SSL_set1_tls_channel_id(NULL, NULL);
             fail();
         } catch (NullPointerException expected) {
         }
@@ -348,25 +347,14 @@
         long s = NativeCrypto.SSL_new(c);
 
         try {
-            NativeCrypto.SSL_set1_tls_channel_id(s, null);
+            NativeCrypto.SSL_set1_tls_channel_id(s, NULL);
             fail();
         } catch (NullPointerException expected) {
         }
 
-        // Use the key via the wrapper that decides whether to use PKCS#8 or native OpenSSL.
-        NativeCrypto.SSL_set1_tls_channel_id(s, CHANNEL_ID_PRIVATE_KEY);
-
-        // Use the key via its PKCS#8 representation.
-        assertEquals("PKCS#8", CHANNEL_ID_PRIVATE_KEY.getFormat());
-        byte[] pkcs8EncodedKeyBytes = CHANNEL_ID_PRIVATE_KEY.getEncoded();
-        assertNotNull(pkcs8EncodedKeyBytes);
-        NativeCrypto.SSL_use_PKCS8_PrivateKey_for_tls_channel_id(s, pkcs8EncodedKeyBytes);
-
         // Use the key natively. This works because the initChannelIdKey method ensures that the
         // key is backed by OpenSSL.
-        NativeCrypto.SSL_use_OpenSSL_PrivateKey_for_tls_channel_id(
-                s,
-                ((OpenSSLECPrivateKey) CHANNEL_ID_PRIVATE_KEY).getOpenSSLKey().getPkeyContext());
+        NativeCrypto.SSL_set1_tls_channel_id(s, CHANNEL_ID_PRIVATE_KEY.getPkeyContext());
 
         NativeCrypto.SSL_free(s);
         NativeCrypto.SSL_CTX_free(c);
@@ -374,7 +362,7 @@
 
     public void test_SSL_use_PrivateKey() throws Exception {
         try {
-            NativeCrypto.SSL_use_PrivateKey(NULL, null);
+            NativeCrypto.SSL_use_PrivateKey(NULL, NULL);
             fail();
         } catch (NullPointerException expected) {
         }
@@ -383,12 +371,12 @@
         long s = NativeCrypto.SSL_new(c);
 
         try {
-            NativeCrypto.SSL_use_PrivateKey(s, null);
+            NativeCrypto.SSL_use_PrivateKey(s, NULL);
             fail();
         } catch (NullPointerException expected) {
         }
 
-        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey());
+        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getPkeyContext());
 
         NativeCrypto.SSL_free(s);
         NativeCrypto.SSL_CTX_free(c);
@@ -430,7 +418,7 @@
         } catch (SSLException expected) {
         }
 
-        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey());
+        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getPkeyContext());
         NativeCrypto.SSL_check_private_key(s);
 
         NativeCrypto.SSL_free(s);
@@ -441,7 +429,7 @@
         long s = NativeCrypto.SSL_new(c);
 
         // first private, then certificate
-        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey());
+        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getPkeyContext());
 
         try {
             NativeCrypto.SSL_check_private_key(s);
@@ -613,7 +601,7 @@
     private static final boolean DEBUG = false;
 
     public static class Hooks {
-        private PrivateKey channelIdPrivateKey;
+        private OpenSSLKey channelIdPrivateKey;
 
         public long getContext() throws SSLException {
             return NativeCrypto.SSL_CTX_new();
@@ -626,7 +614,7 @@
             NativeCrypto.SSL_set_cipher_lists(s, new String[] { "RC4-MD5" });
 
             if (channelIdPrivateKey != null) {
-                NativeCrypto.SSL_set1_tls_channel_id(s, channelIdPrivateKey);
+                NativeCrypto.SSL_set1_tls_channel_id(s, channelIdPrivateKey.getPkeyContext());
             }
             return s;
         }
@@ -721,13 +709,13 @@
     }
 
     public static class ServerHooks extends Hooks {
-        private final byte[] privateKey;
+        private final OpenSSLKey privateKey;
         private final byte[][] certificates;
         private boolean channelIdEnabled;
         private byte[] channelIdAfterHandshake;
         private Throwable channelIdAfterHandshakeException;
 
-        public ServerHooks(byte[] privateKey, byte[][] certificates) {
+        public ServerHooks(OpenSSLKey privateKey, byte[][] certificates) {
             this.privateKey = privateKey;
             this.certificates = certificates;
         }
@@ -736,7 +724,7 @@
         public long beforeHandshake(long c) throws SSLException {
             long s = super.beforeHandshake(c);
             if (privateKey != null) {
-                NativeCrypto.SSL_use_PrivateKey(s, privateKey);
+                NativeCrypto.SSL_use_PrivateKey(s, privateKey.getPkeyContext());
             }
             if (certificates != null) {
                 NativeCrypto.SSL_use_certificate(s, certificates);
@@ -768,7 +756,8 @@
     }
 
     public static Future<TestSSLHandshakeCallbacks> handshake(final ServerSocket listener,
-            final int timeout, final boolean client, final Hooks hooks, final byte[] npnProtocols) {
+            final int timeout, final boolean client, final Hooks hooks, final byte[] npnProtocols,
+            final byte[] alpnProtocols) {
         ExecutorService executor = Executors.newSingleThreadExecutor();
         Future<TestSSLHandshakeCallbacks> future = executor.submit(
                 new Callable<TestSSLHandshakeCallbacks>() {
@@ -797,7 +786,7 @@
                 long session = NULL;
                 try {
                     session = NativeCrypto.SSL_do_handshake(s, fd, callback, timeout, client,
-                                                            npnProtocols);
+                                                            npnProtocols, alpnProtocols);
                     if (DEBUG) {
                         System.out.println("ssl=0x" + Long.toString(s, 16)
                                            + " handshake"
@@ -816,7 +805,7 @@
 
     public void test_SSL_do_handshake_NULL_SSL() throws Exception {
         try {
-            NativeCrypto.SSL_do_handshake(NULL, null, null, 0, false, null);
+            NativeCrypto.SSL_do_handshake(NULL, null, null, 0, false, null, null);
             fail();
         } catch (NullPointerException expected) {
         }
@@ -827,13 +816,13 @@
         long s = NativeCrypto.SSL_new(c);
 
         try {
-            NativeCrypto.SSL_do_handshake(s, null, null, 0, true, null);
+            NativeCrypto.SSL_do_handshake(s, null, null, 0, true, null, null);
             fail();
         } catch (NullPointerException expected) {
         }
 
         try {
-            NativeCrypto.SSL_do_handshake(s, INVALID_FD, null, 0, true, null);
+            NativeCrypto.SSL_do_handshake(s, INVALID_FD, null, 0, true, null, null);
             fail();
         } catch (NullPointerException expected) {
         }
@@ -847,8 +836,8 @@
         final ServerSocket listener = new ServerSocket(0);
         Hooks cHooks = new Hooks();
         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         assertTrue(clientCallback.verifyCertificateChainCalled);
@@ -870,7 +859,7 @@
             @Override
             public void clientCertificateRequested(long s) {
                 super.clientCertificateRequested(s);
-                NativeCrypto.SSL_use_PrivateKey(s, getClientPrivateKey());
+                NativeCrypto.SSL_use_PrivateKey(s, getClientPrivateKey().getPkeyContext());
                 NativeCrypto.SSL_use_certificate(s, getClientCertificates());
             }
         };
@@ -883,8 +872,8 @@
                 return s;
             }
         };
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         assertTrue(clientCallback.verifyCertificateChainCalled);
@@ -928,8 +917,10 @@
                     return s;
                 }
             };
-            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+                    null);
+            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+                    null);
             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
             fail();
         } catch (ExecutionException expected) {
@@ -991,8 +982,8 @@
                 }
             }
         };
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         try {
             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         } catch (ExecutionException e) {
@@ -1010,8 +1001,10 @@
         try {
             Hooks cHooks = new Hooks();
             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
-            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 1, true, cHooks, null);
-            Future<TestSSLHandshakeCallbacks> server = handshake(listener, -1, false, sHooks, null);
+            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 1, true, cHooks, null,
+                    null);
+            Future<TestSSLHandshakeCallbacks> server = handshake(listener, -1, false, sHooks, null,
+                    null);
             serverSocket = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket();
             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
             fail();
@@ -1033,8 +1026,8 @@
         try {
             Hooks cHooks = new Hooks();
             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
-            Future<TestSSLHandshakeCallbacks> client = handshake(listener, -1, true, cHooks, null);
-            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 1, false, sHooks, null);
+            Future<TestSSLHandshakeCallbacks> client = handshake(listener, -1, true, cHooks, null, null);
+            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 1, false, sHooks, null, null);
             clientSocket = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket();
             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
             fail();
@@ -1055,8 +1048,8 @@
         cHooks.channelIdPrivateKey = CHANNEL_ID_PRIVATE_KEY;
         ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
         sHooks.channelIdEnabled = true;
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         assertTrue(clientCallback.verifyCertificateChainCalled);
@@ -1081,8 +1074,8 @@
         cHooks.channelIdPrivateKey = CHANNEL_ID_PRIVATE_KEY;
         ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
         sHooks.channelIdEnabled = false;
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         assertTrue(clientCallback.verifyCertificateChainCalled);
@@ -1107,8 +1100,8 @@
         cHooks.channelIdPrivateKey = null;
         ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
         sHooks.channelIdEnabled = true;
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         assertTrue(clientCallback.verifyCertificateChainCalled);
@@ -1175,9 +1168,9 @@
                     }
                 };
                 Future<TestSSLHandshakeCallbacks> client
-                        = handshake(listener, 0, true, cHooks, null);
+                        = handshake(listener, 0, true, cHooks, null, null);
                 Future<TestSSLHandshakeCallbacks> server
-                        = handshake(listener, 0, false, sHooks, null);
+                        = handshake(listener, 0, false, sHooks, null, null);
                 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
                 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
             }
@@ -1218,9 +1211,9 @@
                     }
                 };
                 Future<TestSSLHandshakeCallbacks> client
-                        = handshake(listener, 0, true, cHooks, null);
+                        = handshake(listener, 0, true, cHooks, null, null);
                 Future<TestSSLHandshakeCallbacks> server
-                        = handshake(listener, 0, false, sHooks, null);
+                        = handshake(listener, 0, false, sHooks, null, null);
                 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
                 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
             }
@@ -1260,8 +1253,10 @@
                 }
             };
             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
-            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+                    null);
+            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+                    null);
             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
             fail();
         } catch (ExecutionException expected) {
@@ -1279,8 +1274,10 @@
                     return s;
                 }
             };
-            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+                    null);
+            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+                    null);
             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
             fail();
         } catch (ExecutionException expected) {
@@ -1347,8 +1344,8 @@
                 super.afterHandshake(session, s, c, sock, fd, callback);
             }
         };
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
@@ -1396,9 +1393,59 @@
 
         ServerSocket listener = new ServerSocket(0);
         Future<TestSSLHandshakeCallbacks> client
-                = handshake(listener, 0, true, cHooks, clientNpnProtocols);
+                = handshake(listener, 0, true, cHooks, clientNpnProtocols, null);
         Future<TestSSLHandshakeCallbacks> server
-                = handshake(listener, 0, false, sHooks, serverNpnProtocols);
+                = handshake(listener, 0, false, sHooks, serverNpnProtocols, null);
+        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+    }
+
+    public void test_SSL_AlpnNegotiateSuccess() throws Exception {
+        final byte[] clientAlpnProtocols = new byte[] {
+                8, 'h', 't', 't', 'p', '/', '1', '.', '1',
+                3, 'f', 'o', 'o',
+                6, 's', 'p', 'd', 'y', '/', '2',
+        };
+        final byte[] serverAlpnProtocols = new byte[] {
+                6, 's', 'p', 'd', 'y', '/', '2',
+                3, 'f', 'o', 'o',
+                3, 'b', 'a', 'r',
+        };
+
+        Hooks cHooks = new Hooks() {
+            @Override public long beforeHandshake(long context) throws SSLException {
+                NativeCrypto.SSL_CTX_set_alpn_protos(context, clientAlpnProtocols);
+                return super.beforeHandshake(context);
+            }
+            @Override public void afterHandshake(long session, long ssl, long context, Socket socket,
+                    FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
+                byte[] negotiated = NativeCrypto.SSL_get0_alpn_selected(ssl);
+                assertEquals("spdy/2", new String(negotiated));
+                /*
+                 * There is no callback on the client, so we can't enable
+                 * cut-through
+                 */
+                assertEquals("ALPN should not enable cutthrough on the client", 0,
+                        NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
+                super.afterHandshake(session, ssl, context, socket, fd, callback);
+            }
+        };
+        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
+            @Override public void afterHandshake(long session, long ssl, long c, Socket sock,
+                    FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
+                byte[] negotiated = NativeCrypto.SSL_get0_alpn_selected(ssl);
+                assertEquals("spdy/2", new String(negotiated));
+                assertEquals("ALPN should not enable cutthrough on the server",
+                        0, NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
+                super.afterHandshake(session, ssl, c, sock, fd, callback);
+            }
+        };
+
+        ServerSocket listener = new ServerSocket(0);
+        Future<TestSSLHandshakeCallbacks> client
+                = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server
+                = handshake(listener, 0, false, sHooks, null, serverAlpnProtocols);
         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
@@ -1451,8 +1498,8 @@
                 super.afterHandshake(session, s, c, sock, fd, callback);
             }
         };
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
@@ -1487,8 +1534,8 @@
                 super.afterHandshake(session, s, c, sock, fd, callback);
             }
         };
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
@@ -1514,8 +1561,8 @@
             }
         };
         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
@@ -1618,8 +1665,10 @@
                     super.afterHandshake(session, s, c, sock, fd, callback);
                 }
             };
-            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+                    null);
+            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+                    null);
             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         }
@@ -1646,8 +1695,10 @@
                     super.afterHandshake(session, s, c, sock, fd, callback);
                 }
             };
-            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+                    null);
+            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+                    null);
             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
             fail();
         } catch (ExecutionException expected) {
@@ -1761,8 +1812,8 @@
                 super.afterHandshake(session, s, c, sock, fd, callback);
             }
         };
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
@@ -1835,8 +1886,8 @@
             }
         };
         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
@@ -1864,8 +1915,10 @@
                 }
             };
             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
-            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+                    null);
+            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+                    null);
             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         }
@@ -1892,8 +1945,8 @@
             }
         };
         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
@@ -1919,8 +1972,8 @@
             }
         };
         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
@@ -1966,8 +2019,8 @@
             }
         };
         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
-        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
-        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
     }
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureTest.java b/crypto/src/test/java/org/conscrypt/OpenSSLSignatureTest.java
similarity index 92%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureTest.java
rename to crypto/src/test/java/org/conscrypt/OpenSSLSignatureTest.java
index 76e423c..045c509 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureTest.java
+++ b/crypto/src/test/java/org/conscrypt/OpenSSLSignatureTest.java
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.security.NoSuchAlgorithmException;
 import junit.framework.TestCase;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLSignature;
 
 public class OpenSSLSignatureTest extends TestCase {
 
diff --git a/crypto/src/test/java/org/conscrypt/SignatureTest.java b/crypto/src/test/java/org/conscrypt/SignatureTest.java
new file mode 100644
index 0000000..d6679c4
--- /dev/null
+++ b/crypto/src/test/java/org/conscrypt/SignatureTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.conscrypt;
+
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.Signature;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Set;
+import junit.framework.TestCase;
+
+public class SignatureTest extends TestCase {
+    // 20 bytes for DSA
+    private final byte[] DATA = new byte[20];
+
+    public void test_getInstance_OpenSSL_ENGINE() throws Exception {
+        final String pem_private = "-----BEGIN RSA PRIVATE KEY-----\n"
+                + "MIICXAIBAAKBgQDpm4KamxulJnycEzNONGM7p0CvAaoZxJEd5Dvio5b6BROdCtRN\n"
+                + "lEsB+9vtB5thkyDVC7N+IW0AjtyDE6h2QP+AWa+c4dh0RM2uNVXkUWPrA8C++GHv\n"
+                + "EDlxZzRGiQEMuippYfIyBVkO+4+GRvnkG4dKjzxrQYPqKUK3C4PgFW2FewIDAQAB\n"
+                + "AoGAGUTSBsk6X03fcr588TundD9uNr/2V1002Ufj1msdnKPJ8FXIiy+8QVWt/2Cw\n"
+                + "RQi2J3VhkAYrlUDex2rr8Qas3E9uuwKgg/MZ4EsJbnKKgkd7uBZfmZ2ogcNJ82u7\n"
+                + "teVijFpdsVLDa9aczEppt5sZzyTaBrovrRb+AIRDpMw3I0ECQQD3JkWeQUA9Is1V\n"
+                + "z0X/ly/kaQKQLlrwYNdiKF0qOpyTLAguI7asAS72Zj7fThk5bHLM+mmgYwkicIIb\n"
+                + "67J32GQbAkEA8fkXqEnwMFYSkRmT9M/qUkwWUsMW12/AoZFI5gwKNDHZYxytGGLw\n"
+                + "mC//0qKnyeUG00vz06vLApe4/Sq4ODe6IQJBALEGastF9ZtUuDsEciD2y8kRJlLb\n"
+                + "wSt4Ug3u13yN6uTHnzxdPFTLrDW1WsdcC1lEQp5rpwjIpxxR9f/FvVl2V40CQHOY\n"
+                + "F6EhkUjGFaCTo4b0PHCMQK3Q3PyWOmP0z+p2HfnJRpx+eoKH4YASjhfF9HoSmywd\n"
+                + "wKGCFD1s1ca7vb29gYECQH86GmYZsDoLNWurEVJbkmCr7X1+xwim6umdrNKR27P7\n"
+                + "F1y0Sa3YY+LiiRb+IRSWE/onlP+28LIzWGF4lcTfDMc=\n"
+                + "-----END RSA PRIVATE KEY-----";
+
+        final byte[] der_public = new byte[] {
+                (byte) 0x30, (byte) 0x81, (byte) 0x9F, (byte) 0x30, (byte) 0x0D, (byte) 0x06,
+                (byte) 0x09, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xF7,
+                (byte) 0x0D, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00,
+                (byte) 0x03, (byte) 0x81, (byte) 0x8D, (byte) 0x00, (byte) 0x30, (byte) 0x81,
+                (byte) 0x89, (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xE9,
+                (byte) 0x9B, (byte) 0x82, (byte) 0x9A, (byte) 0x9B, (byte) 0x1B, (byte) 0xA5,
+                (byte) 0x26, (byte) 0x7C, (byte) 0x9C, (byte) 0x13, (byte) 0x33, (byte) 0x4E,
+                (byte) 0x34, (byte) 0x63, (byte) 0x3B, (byte) 0xA7, (byte) 0x40, (byte) 0xAF,
+                (byte) 0x01, (byte) 0xAA, (byte) 0x19, (byte) 0xC4, (byte) 0x91, (byte) 0x1D,
+                (byte) 0xE4, (byte) 0x3B, (byte) 0xE2, (byte) 0xA3, (byte) 0x96, (byte) 0xFA,
+                (byte) 0x05, (byte) 0x13, (byte) 0x9D, (byte) 0x0A, (byte) 0xD4, (byte) 0x4D,
+                (byte) 0x94, (byte) 0x4B, (byte) 0x01, (byte) 0xFB, (byte) 0xDB, (byte) 0xED,
+                (byte) 0x07, (byte) 0x9B, (byte) 0x61, (byte) 0x93, (byte) 0x20, (byte) 0xD5,
+                (byte) 0x0B, (byte) 0xB3, (byte) 0x7E, (byte) 0x21, (byte) 0x6D, (byte) 0x00,
+                (byte) 0x8E, (byte) 0xDC, (byte) 0x83, (byte) 0x13, (byte) 0xA8, (byte) 0x76,
+                (byte) 0x40, (byte) 0xFF, (byte) 0x80, (byte) 0x59, (byte) 0xAF, (byte) 0x9C,
+                (byte) 0xE1, (byte) 0xD8, (byte) 0x74, (byte) 0x44, (byte) 0xCD, (byte) 0xAE,
+                (byte) 0x35, (byte) 0x55, (byte) 0xE4, (byte) 0x51, (byte) 0x63, (byte) 0xEB,
+                (byte) 0x03, (byte) 0xC0, (byte) 0xBE, (byte) 0xF8, (byte) 0x61, (byte) 0xEF,
+                (byte) 0x10, (byte) 0x39, (byte) 0x71, (byte) 0x67, (byte) 0x34, (byte) 0x46,
+                (byte) 0x89, (byte) 0x01, (byte) 0x0C, (byte) 0xBA, (byte) 0x2A, (byte) 0x69,
+                (byte) 0x61, (byte) 0xF2, (byte) 0x32, (byte) 0x05, (byte) 0x59, (byte) 0x0E,
+                (byte) 0xFB, (byte) 0x8F, (byte) 0x86, (byte) 0x46, (byte) 0xF9, (byte) 0xE4,
+                (byte) 0x1B, (byte) 0x87, (byte) 0x4A, (byte) 0x8F, (byte) 0x3C, (byte) 0x6B,
+                (byte) 0x41, (byte) 0x83, (byte) 0xEA, (byte) 0x29, (byte) 0x42, (byte) 0xB7,
+                (byte) 0x0B, (byte) 0x83, (byte) 0xE0, (byte) 0x15, (byte) 0x6D, (byte) 0x85,
+                (byte) 0x7B, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01
+        };
+
+        // We only need to test this on the OpenSSL provider.
+        Provider p = Security.getProvider(OpenSSLProvider.PROVIDER_NAME);
+
+        /* ENGINE-based private key */
+        NativeCryptoTest.loadTestEngine();
+        OpenSSLEngine engine = OpenSSLEngine.getInstance(NativeCryptoTest.TEST_ENGINE_ID);
+        PrivateKey privKey = engine.getPrivateKeyById(pem_private);
+        assertTrue(privKey instanceof RSAPrivateKey);
+
+        /* Non-ENGINE-based public key */
+        KeyFactory kf = KeyFactory.getInstance("RSA", p);
+        PublicKey pubKey = kf.generatePublic(new X509EncodedKeySpec(der_public));
+
+        KeyPair kp = new KeyPair(pubKey, privKey);
+
+        Set<Provider.Service> services = p.getServices();
+        for (Provider.Service service : services) {
+            if ("Signature".equals(service.getType()) && service.getAlgorithm().contains("RSA")) {
+                Signature sig1 = Signature.getInstance(service.getAlgorithm(), p);
+                test_Signature(sig1, kp);
+            }
+        }
+    }
+
+    private void test_Signature(Signature sig, KeyPair keyPair) throws Exception {
+        sig.initSign(keyPair.getPrivate());
+        sig.update(DATA);
+        byte[] signature = sig.sign();
+        assertNotNull(sig.getAlgorithm(), signature);
+        assertTrue(sig.getAlgorithm(), signature.length > 0);
+
+        sig.initVerify(keyPair.getPublic());
+        sig.update(DATA);
+        assertTrue(sig.getAlgorithm(), sig.verify(signature));
+
+        // After verify, should be reusable as if we are after initVerify
+        sig.update(DATA);
+        assertTrue(sig.getAlgorithm(), sig.verify(signature));
+
+        // Calling Signature.verify a second time should not throw
+        // http://code.google.com/p/android/issues/detail?id=34933
+        sig.verify(signature);
+    }
+}
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImplTest.java b/crypto/src/test/java/org/conscrypt/TrustManagerImplTest.java
similarity index 99%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImplTest.java
rename to crypto/src/test/java/org/conscrypt/TrustManagerImplTest.java
index 9757bc5..639ed95 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImplTest.java
+++ b/crypto/src/test/java/org/conscrypt/TrustManagerImplTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.File;
 import java.io.FileWriter;
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStoreTest.java b/crypto/src/test/java/org/conscrypt/TrustedCertificateStoreTest.java
similarity index 99%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStoreTest.java
rename to crypto/src/test/java/org/conscrypt/TrustedCertificateStoreTest.java
index 8f9b7fa..a8e9475 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStoreTest.java
+++ b/crypto/src/test/java/org/conscrypt/TrustedCertificateStoreTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
 
 import java.io.File;
 import java.io.FileOutputStream;
diff --git a/dalvik/src/main/java/dalvik/annotation/KnownFailure.java b/dalvik/src/main/java/dalvik/annotation/KnownFailure.java
index 11e813d..1d47a72 100644
--- a/dalvik/src/main/java/dalvik/annotation/KnownFailure.java
+++ b/dalvik/src/main/java/dalvik/annotation/KnownFailure.java
@@ -23,7 +23,7 @@
 
 /**
  * Marks a test case as a known failure. This means the underlying
- * implementation should be fixed. Seems to be similar to @code{@ToBeFixed}, so
+ * implementation should be fixed. Seems to be similar to {@code @ToBeFixed}, so
  * maybe the two can be merged at some point.
  *
  * @hide
diff --git a/dalvik/src/main/java/dalvik/annotation/TestTarget.java b/dalvik/src/main/java/dalvik/annotation/TestTarget.java
index dcfd20ca..a2f94a1 100644
--- a/dalvik/src/main/java/dalvik/annotation/TestTarget.java
+++ b/dalvik/src/main/java/dalvik/annotation/TestTarget.java
@@ -26,7 +26,7 @@
  * specifies a single method target for the test (but can be used multiple
  * times).
  *
- * @deprecated Obsolete
+ * @deprecated Obsolete.
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ ElementType.ANNOTATION_TYPE })
diff --git a/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java b/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java
index e88040e..1e16d0c 100644
--- a/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java
+++ b/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java
@@ -27,7 +27,7 @@
  * organized according to the API classes they test. Might be too strict for
  * some cases.
  *
- * @deprecated Obsolete
+ * @deprecated Obsolete.
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ ElementType.TYPE })
diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java
index d61f0e1..b9de236 100644
--- a/dalvik/src/main/java/dalvik/system/BlockGuard.java
+++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java
@@ -22,7 +22,6 @@
 import java.io.IOException;
 import java.math.BigInteger;
 import java.net.SocketException;
-import java.nio.charset.Charsets;
 
 /**
  * Mechanism to let threads set restrictions on what code is allowed
diff --git a/dalvik/src/main/java/dalvik/system/Zygote.java b/dalvik/src/main/java/dalvik/system/Zygote.java
index 9e96204..ea9dbdc 100644
--- a/dalvik/src/main/java/dalvik/system/Zygote.java
+++ b/dalvik/src/main/java/dalvik/system/Zygote.java
@@ -119,7 +119,7 @@
      * dimension having a length of 3 and representing
      * (resource, rlim_cur, rlim_max). These are set via the posix
      * setrlimit(2) call.
-     * @param seInfo null-ok a string specifying SEAndroid information for
+     * @param seInfo null-ok a string specifying SELinux information for
      * the new process.
      * @param niceName null-ok a string specifying the process name.
      *
diff --git a/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp b/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
index 11735eb..52f22a8 100644
--- a/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
+++ b/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
@@ -17,7 +17,7 @@
 #define LOG_TAG "NativeTestTarget"
 
 #include "JNIHelp.h"
-#include "../../../../luni/src/main/native/JniConstants.h"
+#include "JniConstants.h"
 
 static void NativeTestTarget_emptyJniMethod0(JNIEnv*, jobject) { }
 static void NativeTestTarget_emptyJniMethod6(JNIEnv*, jclass, int, int, int, int, int, int) { }
diff --git a/dex/src/main/java/com/android/dex/Annotation.java b/dex/src/main/java/com/android/dex/Annotation.java
new file mode 100644
index 0000000..e5ef978
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/Annotation.java
@@ -0,0 +1,63 @@
+/*
+ * 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 com.android.dex;
+
+import static com.android.dex.EncodedValueReader.ENCODED_ANNOTATION;
+
+/**
+ * An annotation.
+ */
+public final class Annotation implements Comparable<Annotation> {
+    private final Dex dex;
+    private final byte visibility;
+    private final EncodedValue encodedAnnotation;
+
+    public Annotation(Dex dex, byte visibility, EncodedValue encodedAnnotation) {
+        this.dex = dex;
+        this.visibility = visibility;
+        this.encodedAnnotation = encodedAnnotation;
+    }
+
+    public byte getVisibility() {
+        return visibility;
+    }
+
+    public EncodedValueReader getReader() {
+        return new EncodedValueReader(encodedAnnotation, ENCODED_ANNOTATION);
+    }
+
+    public int getTypeIndex() {
+        EncodedValueReader reader = getReader();
+        reader.readAnnotation();
+        return reader.getAnnotationType();
+    }
+
+    public void writeTo(Dex.Section out) {
+        out.writeByte(visibility);
+        encodedAnnotation.writeTo(out);
+    }
+
+    @Override public int compareTo(Annotation other) {
+        return encodedAnnotation.compareTo(other.encodedAnnotation);
+    }
+
+    @Override public String toString() {
+        return dex == null
+                ? visibility + " " + getTypeIndex()
+                : visibility + " " + dex.typeNames().get(getTypeIndex());
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/ClassData.java b/dex/src/main/java/com/android/dex/ClassData.java
new file mode 100644
index 0000000..840756c
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/ClassData.java
@@ -0,0 +1,104 @@
+/*
+ * 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 com.android.dex;
+
+public final class ClassData {
+    private final Field[] staticFields;
+    private final Field[] instanceFields;
+    private final Method[] directMethods;
+    private final Method[] virtualMethods;
+
+    public ClassData(Field[] staticFields, Field[] instanceFields,
+            Method[] directMethods, Method[] virtualMethods) {
+        this.staticFields = staticFields;
+        this.instanceFields = instanceFields;
+        this.directMethods = directMethods;
+        this.virtualMethods = virtualMethods;
+    }
+
+    public Field[] getStaticFields() {
+        return staticFields;
+    }
+
+    public Field[] getInstanceFields() {
+        return instanceFields;
+    }
+
+    public Method[] getDirectMethods() {
+        return directMethods;
+    }
+
+    public Method[] getVirtualMethods() {
+        return virtualMethods;
+    }
+
+    public Field[] allFields() {
+        Field[] result = new Field[staticFields.length + instanceFields.length];
+        System.arraycopy(staticFields, 0, result, 0, staticFields.length);
+        System.arraycopy(instanceFields, 0, result, staticFields.length, instanceFields.length);
+        return result;
+    }
+
+    public Method[] allMethods() {
+        Method[] result = new Method[directMethods.length + virtualMethods.length];
+        System.arraycopy(directMethods, 0, result, 0, directMethods.length);
+        System.arraycopy(virtualMethods, 0, result, directMethods.length, virtualMethods.length);
+        return result;
+    }
+
+    public static class Field {
+        private final int fieldIndex;
+        private final int accessFlags;
+
+        public Field(int fieldIndex, int accessFlags) {
+            this.fieldIndex = fieldIndex;
+            this.accessFlags = accessFlags;
+        }
+
+        public int getFieldIndex() {
+            return fieldIndex;
+        }
+
+        public int getAccessFlags() {
+            return accessFlags;
+        }
+    }
+
+    public static class Method {
+        private final int methodIndex;
+        private final int accessFlags;
+        private final int codeOffset;
+
+        public Method(int methodIndex, int accessFlags, int codeOffset) {
+            this.methodIndex = methodIndex;
+            this.accessFlags = accessFlags;
+            this.codeOffset = codeOffset;
+        }
+
+        public int getMethodIndex() {
+            return methodIndex;
+        }
+
+        public int getAccessFlags() {
+            return accessFlags;
+        }
+
+        public int getCodeOffset() {
+            return codeOffset;
+        }
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/ClassDef.java b/dex/src/main/java/com/android/dex/ClassDef.java
new file mode 100644
index 0000000..b3225ec
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/ClassDef.java
@@ -0,0 +1,102 @@
+/*
+ * 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 com.android.dex;
+
+/**
+ * A type definition.
+ */
+public final class ClassDef {
+    public static final int NO_INDEX = -1;
+    private final Dex buffer;
+    private final int offset;
+    private final int typeIndex;
+    private final int accessFlags;
+    private final int supertypeIndex;
+    private final int interfacesOffset;
+    private final int sourceFileIndex;
+    private final int annotationsOffset;
+    private final int classDataOffset;
+    private final int staticValuesOffset;
+
+    public ClassDef(Dex buffer, int offset, int typeIndex, int accessFlags,
+            int supertypeIndex, int interfacesOffset, int sourceFileIndex,
+            int annotationsOffset, int classDataOffset, int staticValuesOffset) {
+        this.buffer = buffer;
+        this.offset = offset;
+        this.typeIndex = typeIndex;
+        this.accessFlags = accessFlags;
+        this.supertypeIndex = supertypeIndex;
+        this.interfacesOffset = interfacesOffset;
+        this.sourceFileIndex = sourceFileIndex;
+        this.annotationsOffset = annotationsOffset;
+        this.classDataOffset = classDataOffset;
+        this.staticValuesOffset = staticValuesOffset;
+    }
+
+    public int getOffset() {
+        return offset;
+    }
+
+    public int getTypeIndex() {
+        return typeIndex;
+    }
+
+    public int getSupertypeIndex() {
+        return supertypeIndex;
+    }
+
+    public int getInterfacesOffset() {
+        return interfacesOffset;
+    }
+
+    public short[] getInterfaces() {
+        return buffer.readTypeList(interfacesOffset).getTypes();
+    }
+
+    public int getAccessFlags() {
+        return accessFlags;
+    }
+
+    public int getSourceFileIndex() {
+        return sourceFileIndex;
+    }
+
+    public int getAnnotationsOffset() {
+        return annotationsOffset;
+    }
+
+    public int getClassDataOffset() {
+        return classDataOffset;
+    }
+
+    public int getStaticValuesOffset() {
+        return staticValuesOffset;
+    }
+
+    @Override public String toString() {
+        if (buffer == null) {
+            return typeIndex + " " + supertypeIndex;
+        }
+
+        StringBuilder result = new StringBuilder();
+        result.append(buffer.typeNames().get(typeIndex));
+        if (supertypeIndex != NO_INDEX) {
+            result.append(" extends ").append(buffer.typeNames().get(supertypeIndex));
+        }
+        return result.toString();
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/Code.java b/dex/src/main/java/com/android/dex/Code.java
new file mode 100644
index 0000000..9258af7
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/Code.java
@@ -0,0 +1,124 @@
+/*
+ * 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 com.android.dex;
+
+public final class Code {
+    private final int registersSize;
+    private final int insSize;
+    private final int outsSize;
+    private final int debugInfoOffset;
+    private final short[] instructions;
+    private final Try[] tries;
+    private final CatchHandler[] catchHandlers;
+
+    public Code(int registersSize, int insSize, int outsSize, int debugInfoOffset,
+            short[] instructions, Try[] tries, CatchHandler[] catchHandlers) {
+        this.registersSize = registersSize;
+        this.insSize = insSize;
+        this.outsSize = outsSize;
+        this.debugInfoOffset = debugInfoOffset;
+        this.instructions = instructions;
+        this.tries = tries;
+        this.catchHandlers = catchHandlers;
+    }
+
+    public int getRegistersSize() {
+        return registersSize;
+    }
+
+    public int getInsSize() {
+        return insSize;
+    }
+
+    public int getOutsSize() {
+        return outsSize;
+    }
+
+    public int getDebugInfoOffset() {
+        return debugInfoOffset;
+    }
+
+    public short[] getInstructions() {
+        return instructions;
+    }
+
+    public Try[] getTries() {
+        return tries;
+    }
+
+    public CatchHandler[] getCatchHandlers() {
+        return catchHandlers;
+    }
+
+    public static class Try {
+        final int startAddress;
+        final int instructionCount;
+        final int catchHandlerIndex;
+
+        Try(int startAddress, int instructionCount, int catchHandlerIndex) {
+            this.startAddress = startAddress;
+            this.instructionCount = instructionCount;
+            this.catchHandlerIndex = catchHandlerIndex;
+        }
+
+        public int getStartAddress() {
+            return startAddress;
+        }
+
+        public int getInstructionCount() {
+            return instructionCount;
+        }
+
+        /**
+         * Returns this try's catch handler <strong>index</strong>. Note that
+         * this is distinct from the its catch handler <strong>offset</strong>.
+         */
+        public int getCatchHandlerIndex() {
+            return catchHandlerIndex;
+        }
+    }
+
+    public static class CatchHandler {
+        final int[] typeIndexes;
+        final int[] addresses;
+        final int catchAllAddress;
+        final int offset;
+
+        public CatchHandler(int[] typeIndexes, int[] addresses, int catchAllAddress, int offset) {
+            this.typeIndexes = typeIndexes;
+            this.addresses = addresses;
+            this.catchAllAddress = catchAllAddress;
+            this.offset = offset;
+        }
+
+        public int[] getTypeIndexes() {
+            return typeIndexes;
+        }
+
+        public int[] getAddresses() {
+            return addresses;
+        }
+
+        public int getCatchAllAddress() {
+            return catchAllAddress;
+        }
+
+        public int getOffset() {
+            return offset;
+        }
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/Dex.java b/dex/src/main/java/com/android/dex/Dex.java
new file mode 100644
index 0000000..29cd30e
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/Dex.java
@@ -0,0 +1,791 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.Code.CatchHandler;
+import com.android.dex.Code.Try;
+import com.android.dex.util.ByteInput;
+import com.android.dex.util.ByteOutput;
+import com.android.dex.util.FileUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UTFDataFormatException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.AbstractList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.RandomAccess;
+import java.util.zip.Adler32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * The bytes of a dex file in memory for reading and writing. All int offsets
+ * are unsigned.
+ */
+public final class Dex {
+    private static final int CHECKSUM_OFFSET = 8;
+    private static final int CHECKSUM_SIZE = 4;
+    private static final int SIGNATURE_OFFSET = CHECKSUM_OFFSET + CHECKSUM_SIZE;
+    private static final int SIGNATURE_SIZE = 20;
+
+    private ByteBuffer data;
+    private final TableOfContents tableOfContents = new TableOfContents();
+    private int nextSectionStart = 0;
+
+    private static abstract class AbstractRandomAccessList<T>
+            extends AbstractList<T> implements RandomAccess {
+    }
+
+    private List<String> strings = new AbstractRandomAccessList<String>() {
+        @Override public String get(int index) {
+            checkBounds(index, tableOfContents.stringIds.size);
+            return open(tableOfContents.stringIds.off + (index * SizeOf.STRING_ID_ITEM))
+                    .readString();
+        }
+        @Override public int size() {
+            return tableOfContents.stringIds.size;
+        }
+    };
+
+    private final List<Integer> typeIds = new AbstractRandomAccessList<Integer>() {
+        @Override public Integer get(int index) {
+            checkBounds(index, tableOfContents.typeIds.size);
+            return open(tableOfContents.typeIds.off + (index * SizeOf.TYPE_ID_ITEM)).readInt();
+        }
+        @Override public int size() {
+            return tableOfContents.typeIds.size;
+        }
+    };
+
+    private final List<String> typeNames = new AbstractRandomAccessList<String>() {
+        @Override public String get(int index) {
+            checkBounds(index, tableOfContents.typeIds.size);
+            return strings.get(typeIds.get(index));
+        }
+        @Override public int size() {
+            return tableOfContents.typeIds.size;
+        }
+    };
+
+    private final List<ProtoId> protoIds = new AbstractRandomAccessList<ProtoId>() {
+        @Override public ProtoId get(int index) {
+            checkBounds(index, tableOfContents.protoIds.size);
+            return open(tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * index))
+                    .readProtoId();
+        }
+        @Override public int size() {
+            return tableOfContents.protoIds.size;
+        }
+    };
+
+    private final List<FieldId> fieldIds = new AbstractRandomAccessList<FieldId>() {
+        @Override public FieldId get(int index) {
+            checkBounds(index, tableOfContents.fieldIds.size);
+            return open(tableOfContents.fieldIds.off + (SizeOf.MEMBER_ID_ITEM * index))
+                    .readFieldId();
+        }
+        @Override public int size() {
+            return tableOfContents.fieldIds.size;
+        }
+    };
+
+    private final List<MethodId> methodIds = new AbstractRandomAccessList<MethodId>() {
+        @Override public MethodId get(int index) {
+            checkBounds(index, tableOfContents.methodIds.size);
+            return open(tableOfContents.methodIds.off + (SizeOf.MEMBER_ID_ITEM * index))
+                    .readMethodId();
+        }
+        @Override public int size() {
+            return tableOfContents.methodIds.size;
+        }
+    };
+
+    /**
+     * Creates a new dex that reads from {@code data}. It is an error to modify
+     * {@code data} after using it to create a dex buffer.
+     */
+    public Dex(byte[] data) throws IOException {
+        this(ByteBuffer.wrap(data));
+    }
+
+    private Dex(ByteBuffer data) throws IOException {
+        this.data = data;
+        this.data.order(ByteOrder.LITTLE_ENDIAN);
+        this.tableOfContents.readFrom(this);
+    }
+
+    /**
+     * Creates a new empty dex of the specified size.
+     */
+    public Dex(int byteCount) throws IOException {
+        this.data = ByteBuffer.wrap(new byte[byteCount]);
+        this.data.order(ByteOrder.LITTLE_ENDIAN);
+    }
+
+    /**
+     * Creates a new dex buffer of the dex in {@code in}, and closes {@code in}.
+     */
+    public Dex(InputStream in) throws IOException {
+        loadFrom(in);
+    }
+
+    /**
+     * Creates a new dex buffer from the dex file {@code file}.
+     */
+    public Dex(File file) throws IOException {
+        if (FileUtils.hasArchiveSuffix(file.getName())) {
+            ZipFile zipFile = new ZipFile(file);
+            ZipEntry entry = zipFile.getEntry(DexFormat.DEX_IN_JAR_NAME);
+            if (entry != null) {
+                loadFrom(zipFile.getInputStream(entry));
+                zipFile.close();
+            } else {
+                throw new DexException("Expected " + DexFormat.DEX_IN_JAR_NAME + " in " + file);
+            }
+        } else if (file.getName().endsWith(".dex")) {
+            loadFrom(new FileInputStream(file));
+        } else {
+            throw new DexException("unknown output extension: " + file);
+        }
+    }
+
+    /**
+     * Creates a new dex from the contents of {@code bytes}. This API supports
+     * both {@code .dex} and {@code .odex} input. Calling this constructor
+     * transfers ownership of {@code bytes} to the returned Dex: it is an error
+     * to access the buffer after calling this method.
+     */
+    public static Dex create(ByteBuffer data) throws IOException {
+        data.order(ByteOrder.LITTLE_ENDIAN);
+
+        // if it's an .odex file, set position and limit to the .dex section
+        if (data.get(0) == 'd'
+                && data.get(1) == 'e'
+                && data.get(2) == 'y'
+                && data.get(3) == '\n') {
+            data.position(8);
+            int offset = data.getInt();
+            int length = data.getInt();
+            data.position(offset);
+            data.limit(offset + length);
+            data = data.slice();
+        }
+
+        return new Dex(data);
+    }
+
+    private void loadFrom(InputStream in) throws IOException {
+        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+        byte[] buffer = new byte[8192];
+
+        int count;
+        while ((count = in.read(buffer)) != -1) {
+            bytesOut.write(buffer, 0, count);
+        }
+        in.close();
+
+        this.data = ByteBuffer.wrap(bytesOut.toByteArray());
+        this.data.order(ByteOrder.LITTLE_ENDIAN);
+        this.tableOfContents.readFrom(this);
+    }
+
+    private static void checkBounds(int index, int length) {
+        if (index < 0 || index >= length) {
+            throw new IndexOutOfBoundsException("index:" + index + ", length=" + length);
+        }
+    }
+
+    public void writeTo(OutputStream out) throws IOException {
+        byte[] buffer = new byte[8192];
+        ByteBuffer data = this.data.duplicate(); // positioned ByteBuffers aren't thread safe
+        data.clear();
+        while (data.hasRemaining()) {
+            int count = Math.min(buffer.length, data.remaining());
+            data.get(buffer, 0, count);
+            out.write(buffer, 0, count);
+        }
+    }
+
+    public void writeTo(File dexOut) throws IOException {
+        OutputStream out = new FileOutputStream(dexOut);
+        writeTo(out);
+        out.close();
+    }
+
+    public TableOfContents getTableOfContents() {
+        return tableOfContents;
+    }
+
+    public Section open(int position) {
+        if (position < 0 || position >= data.capacity()) {
+            throw new IllegalArgumentException("position=" + position
+                    + " length=" + data.capacity());
+        }
+        ByteBuffer sectionData = data.duplicate();
+        sectionData.order(ByteOrder.LITTLE_ENDIAN); // necessary?
+        sectionData.position(position);
+        sectionData.limit(data.capacity());
+        return new Section("section", sectionData);
+    }
+
+    public Section appendSection(int maxByteCount, String name) {
+        if ((maxByteCount & 3) != 0) {
+            throw new IllegalStateException("Not four byte aligned!");
+        }
+        int limit = nextSectionStart + maxByteCount;
+        ByteBuffer sectionData = data.duplicate();
+        sectionData.order(ByteOrder.LITTLE_ENDIAN); // necessary?
+        sectionData.position(nextSectionStart);
+        sectionData.limit(limit);
+        Section result = new Section(name, sectionData);
+        nextSectionStart = limit;
+        return result;
+    }
+
+    public int getLength() {
+        return data.capacity();
+    }
+
+    public int getNextSectionStart() {
+        return nextSectionStart;
+    }
+
+    /**
+     * Returns a copy of the the bytes of this dex.
+     */
+    public byte[] getBytes() {
+        ByteBuffer data = this.data.duplicate(); // positioned ByteBuffers aren't thread safe
+        byte[] result = new byte[data.capacity()];
+        data.position(0);
+        data.get(result);
+        return result;
+    }
+
+    public List<String> strings() {
+        return strings;
+    }
+
+    public List<Integer> typeIds() {
+        return typeIds;
+    }
+
+    public List<String> typeNames() {
+        return typeNames;
+    }
+
+    public List<ProtoId> protoIds() {
+        return protoIds;
+    }
+
+    public List<FieldId> fieldIds() {
+        return fieldIds;
+    }
+
+    public List<MethodId> methodIds() {
+        return methodIds;
+    }
+
+    public Iterable<ClassDef> classDefs() {
+        return new Iterable<ClassDef>() {
+            public Iterator<ClassDef> iterator() {
+                if (!tableOfContents.classDefs.exists()) {
+                    return Collections.<ClassDef>emptySet().iterator();
+                }
+                return new Iterator<ClassDef>() {
+                    private Dex.Section in = open(tableOfContents.classDefs.off);
+                    private int count = 0;
+
+                    public boolean hasNext() {
+                        return count < tableOfContents.classDefs.size;
+                    }
+                    public ClassDef next() {
+                        if (!hasNext()) {
+                            throw new NoSuchElementException();
+                        }
+                        count++;
+                        return in.readClassDef();
+                    }
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+        };
+    }
+
+    public TypeList readTypeList(int offset) {
+        if (offset == 0) {
+            return TypeList.EMPTY;
+        }
+        return open(offset).readTypeList();
+    }
+
+    public ClassData readClassData(ClassDef classDef) {
+        int offset = classDef.getClassDataOffset();
+        if (offset == 0) {
+            throw new IllegalArgumentException("offset == 0");
+        }
+        return open(offset).readClassData();
+    }
+
+    public Code readCode(ClassData.Method method) {
+        int offset = method.getCodeOffset();
+        if (offset == 0) {
+            throw new IllegalArgumentException("offset == 0");
+        }
+        return open(offset).readCode();
+    }
+
+    /**
+     * Returns the signature of all but the first 32 bytes of this dex. The
+     * first 32 bytes of dex files are not specified to be included in the
+     * signature.
+     */
+    public byte[] computeSignature() throws IOException {
+        MessageDigest digest;
+        try {
+            digest = MessageDigest.getInstance("SHA-1");
+        } catch (NoSuchAlgorithmException e) {
+            throw new AssertionError();
+        }
+        byte[] buffer = new byte[8192];
+        ByteBuffer data = this.data.duplicate(); // positioned ByteBuffers aren't thread safe
+        data.limit(data.capacity());
+        data.position(SIGNATURE_OFFSET + SIGNATURE_SIZE);
+        while (data.hasRemaining()) {
+            int count = Math.min(buffer.length, data.remaining());
+            data.get(buffer, 0, count);
+            digest.update(buffer, 0, count);
+        }
+        return digest.digest();
+    }
+
+    /**
+     * Returns the checksum of all but the first 12 bytes of {@code dex}.
+     */
+    public int computeChecksum() throws IOException {
+        Adler32 adler32 = new Adler32();
+        byte[] buffer = new byte[8192];
+        ByteBuffer data = this.data.duplicate(); // positioned ByteBuffers aren't thread safe
+        data.limit(data.capacity());
+        data.position(CHECKSUM_OFFSET + CHECKSUM_SIZE);
+        while (data.hasRemaining()) {
+            int count = Math.min(buffer.length, data.remaining());
+            data.get(buffer, 0, count);
+            adler32.update(buffer, 0, count);
+        }
+        return (int) adler32.getValue();
+    }
+
+    /**
+     * Generates the signature and checksum of the dex file {@code out} and
+     * writes them to the file.
+     */
+    public void writeHashes() throws IOException {
+        open(SIGNATURE_OFFSET).write(computeSignature());
+        open(CHECKSUM_OFFSET).writeInt(computeChecksum());
+    }
+
+    public final class Section implements ByteInput, ByteOutput {
+        private final String name;
+        private final ByteBuffer data;
+        private final int initialPosition;
+
+        private Section(String name, ByteBuffer data) {
+            this.name = name;
+            this.data = data;
+            this.initialPosition = data.position();
+        }
+
+        public int getPosition() {
+            return data.position();
+        }
+
+        public int readInt() {
+            return data.getInt();
+        }
+
+        public short readShort() {
+            return data.getShort();
+        }
+
+        public int readUnsignedShort() {
+            return readShort() & 0xffff;
+        }
+
+        public byte readByte() {
+            return data.get();
+        }
+
+        public byte[] readByteArray(int length) {
+            byte[] result = new byte[length];
+            data.get(result);
+            return result;
+        }
+
+        public short[] readShortArray(int length) {
+            short[] result = new short[length];
+            for (int i = 0; i < length; i++) {
+                result[i] = readShort();
+            }
+            return result;
+        }
+
+        public int readUleb128() {
+            return Leb128.readUnsignedLeb128(this);
+        }
+
+        public int readUleb128p1() {
+            return Leb128.readUnsignedLeb128(this) - 1;
+        }
+
+        public int readSleb128() {
+            return Leb128.readSignedLeb128(this);
+        }
+
+        public void writeUleb128p1(int i) {
+            writeUleb128(i + 1);
+        }
+
+        public TypeList readTypeList() {
+            int size = readInt();
+            short[] types = new short[size];
+            for (int i = 0; i < size; i++) {
+                types[i] = readShort();
+            }
+            alignToFourBytes();
+            return new TypeList(Dex.this, types);
+        }
+
+        public String readString() {
+            int offset = readInt();
+            int savedPosition = data.position();
+            int savedLimit = data.limit();
+            data.position(offset);
+            data.limit(data.capacity());
+            try {
+                int expectedLength = readUleb128();
+                String result = Mutf8.decode(this, new char[expectedLength]);
+                if (result.length() != expectedLength) {
+                    throw new DexException("Declared length " + expectedLength
+                            + " doesn't match decoded length of " + result.length());
+                }
+                return result;
+            } catch (UTFDataFormatException e) {
+                throw new DexException(e);
+            } finally {
+                data.position(savedPosition);
+                data.limit(savedLimit);
+            }
+        }
+
+        public FieldId readFieldId() {
+            int declaringClassIndex = readUnsignedShort();
+            int typeIndex = readUnsignedShort();
+            int nameIndex = readInt();
+            return new FieldId(Dex.this, declaringClassIndex, typeIndex, nameIndex);
+        }
+
+        public MethodId readMethodId() {
+            int declaringClassIndex = readUnsignedShort();
+            int protoIndex = readUnsignedShort();
+            int nameIndex = readInt();
+            return new MethodId(Dex.this, declaringClassIndex, protoIndex, nameIndex);
+        }
+
+        public ProtoId readProtoId() {
+            int shortyIndex = readInt();
+            int returnTypeIndex = readInt();
+            int parametersOffset = readInt();
+            return new ProtoId(Dex.this, shortyIndex, returnTypeIndex, parametersOffset);
+        }
+
+        public ClassDef readClassDef() {
+            int offset = getPosition();
+            int type = readInt();
+            int accessFlags = readInt();
+            int supertype = readInt();
+            int interfacesOffset = readInt();
+            int sourceFileIndex = readInt();
+            int annotationsOffset = readInt();
+            int classDataOffset = readInt();
+            int staticValuesOffset = readInt();
+            return new ClassDef(Dex.this, offset, type, accessFlags, supertype,
+                    interfacesOffset, sourceFileIndex, annotationsOffset, classDataOffset,
+                    staticValuesOffset);
+        }
+
+        private Code readCode() {
+            int registersSize = readUnsignedShort();
+            int insSize = readUnsignedShort();
+            int outsSize = readUnsignedShort();
+            int triesSize = readUnsignedShort();
+            int debugInfoOffset = readInt();
+            int instructionsSize = readInt();
+            short[] instructions = readShortArray(instructionsSize);
+            Try[] tries;
+            CatchHandler[] catchHandlers;
+            if (triesSize > 0) {
+              if (instructions.length % 2 == 1) {
+                  readShort(); // padding
+              }
+
+              /*
+               * We can't read the tries until we've read the catch handlers.
+               * Unfortunately they're in the opposite order in the dex file
+               * so we need to read them out-of-order.
+               */
+              Section triesSection = open(data.position());
+              skip(triesSize * SizeOf.TRY_ITEM);
+              catchHandlers = readCatchHandlers();
+              tries = triesSection.readTries(triesSize, catchHandlers);
+          } else {
+              tries = new Try[0];
+              catchHandlers = new CatchHandler[0];
+          }
+          return new Code(registersSize, insSize, outsSize, debugInfoOffset, instructions,
+                  tries, catchHandlers);
+        }
+
+        private CatchHandler[] readCatchHandlers() {
+          int baseOffset = data.position();
+          int catchHandlersSize = readUleb128();
+          CatchHandler[] result = new CatchHandler[catchHandlersSize];
+          for (int i = 0; i < catchHandlersSize; i++) {
+            int offset = data.position() - baseOffset;
+            result[i] = readCatchHandler(offset);
+          }
+          return result;
+        }
+
+        private Try[] readTries(int triesSize, CatchHandler[] catchHandlers) {
+          Try[] result = new Try[triesSize];
+          for (int i = 0; i < triesSize; i++) {
+            int startAddress = readInt();
+            int instructionCount = readUnsignedShort();
+            int handlerOffset = readUnsignedShort();
+            int catchHandlerIndex = findCatchHandlerIndex(catchHandlers, handlerOffset);
+            result[i] = new Try(startAddress, instructionCount, catchHandlerIndex);
+          }
+          return result;
+        }
+
+        private int findCatchHandlerIndex(CatchHandler[] catchHandlers, int offset) {
+          for (int i = 0; i < catchHandlers.length; i++) {
+            CatchHandler catchHandler = catchHandlers[i];
+            if (catchHandler.getOffset() == offset) {
+              return i;
+            }
+          }
+          throw new IllegalArgumentException();
+        }
+
+        private CatchHandler readCatchHandler(int offset) {
+          int size = readSleb128();
+          int handlersCount = Math.abs(size);
+          int[] typeIndexes = new int[handlersCount];
+          int[] addresses = new int[handlersCount];
+          for (int i = 0; i < handlersCount; i++) {
+            typeIndexes[i] = readUleb128();
+            addresses[i] = readUleb128();
+          }
+          int catchAllAddress = size <= 0 ? readUleb128() : -1;
+          return new CatchHandler(typeIndexes, addresses, catchAllAddress, offset);
+        }
+
+        private ClassData readClassData() {
+            int staticFieldsSize = readUleb128();
+            int instanceFieldsSize = readUleb128();
+            int directMethodsSize = readUleb128();
+            int virtualMethodsSize = readUleb128();
+            ClassData.Field[] staticFields = readFields(staticFieldsSize);
+            ClassData.Field[] instanceFields = readFields(instanceFieldsSize);
+            ClassData.Method[] directMethods = readMethods(directMethodsSize);
+            ClassData.Method[] virtualMethods = readMethods(virtualMethodsSize);
+            return new ClassData(staticFields, instanceFields, directMethods, virtualMethods);
+        }
+
+        private ClassData.Field[] readFields(int count) {
+            ClassData.Field[] result = new ClassData.Field[count];
+            int fieldIndex = 0;
+            for (int i = 0; i < count; i++) {
+                fieldIndex += readUleb128(); // field index diff
+                int accessFlags = readUleb128();
+                result[i] = new ClassData.Field(fieldIndex, accessFlags);
+            }
+            return result;
+        }
+
+        private ClassData.Method[] readMethods(int count) {
+            ClassData.Method[] result = new ClassData.Method[count];
+            int methodIndex = 0;
+            for (int i = 0; i < count; i++) {
+                methodIndex += readUleb128(); // method index diff
+                int accessFlags = readUleb128();
+                int codeOff = readUleb128();
+                result[i] = new ClassData.Method(methodIndex, accessFlags, codeOff);
+            }
+            return result;
+        }
+
+        /**
+         * Returns a byte array containing the bytes from {@code start} to this
+         * section's current position.
+         */
+        private byte[] getBytesFrom(int start) {
+            int end = data.position();
+            byte[] result = new byte[end - start];
+            data.position(start);
+            data.get(result);
+            return result;
+        }
+
+        public Annotation readAnnotation() {
+            byte visibility = readByte();
+            int start = data.position();
+            new EncodedValueReader(this, EncodedValueReader.ENCODED_ANNOTATION).skipValue();
+            return new Annotation(Dex.this, visibility, new EncodedValue(getBytesFrom(start)));
+        }
+
+        public EncodedValue readEncodedArray() {
+            int start = data.position();
+            new EncodedValueReader(this, EncodedValueReader.ENCODED_ARRAY).skipValue();
+            return new EncodedValue(getBytesFrom(start));
+        }
+
+        public void skip(int count) {
+          if (count < 0) {
+              throw new IllegalArgumentException();
+          }
+          data.position(data.position() + count);
+      }
+
+        /**
+         * Skips bytes until the position is aligned to a multiple of 4.
+         */
+        public void alignToFourBytes() {
+            data.position((data.position() + 3) & ~3);
+        }
+
+        /**
+         * Writes 0x00 until the position is aligned to a multiple of 4.
+         */
+        public void alignToFourBytesWithZeroFill() {
+            while ((data.position() & 3) != 0) {
+                data.put((byte) 0);
+            }
+        }
+
+        public void assertFourByteAligned() {
+            if ((data.position() & 3) != 0) {
+                throw new IllegalStateException("Not four byte aligned!");
+            }
+        }
+
+        public void write(byte[] bytes) {
+            this.data.put(bytes);
+        }
+
+        public void writeByte(int b) {
+            data.put((byte) b);
+        }
+
+        public void writeShort(short i) {
+            data.putShort(i);
+        }
+
+        public void writeUnsignedShort(int i) {
+            short s = (short) i;
+            if (i != (s & 0xffff)) {
+                throw new IllegalArgumentException("Expected an unsigned short: " + i);
+            }
+            writeShort(s);
+        }
+
+        public void write(short[] shorts) {
+            for (short s : shorts) {
+                writeShort(s);
+            }
+        }
+
+        public void writeInt(int i) {
+            data.putInt(i);
+        }
+
+        public void writeUleb128(int i) {
+            try {
+                Leb128.writeUnsignedLeb128(this, i);
+            } catch (ArrayIndexOutOfBoundsException e) {
+                throw new DexException("Section limit " + data.limit() + " exceeded by " + name);
+            }
+        }
+
+        public void writeSleb128(int i) {
+            try {
+                Leb128.writeSignedLeb128(this, i);
+            } catch (ArrayIndexOutOfBoundsException e) {
+                throw new DexException("Section limit " + data.limit() + " exceeded by " + name);
+            }
+        }
+
+        public void writeStringData(String value) {
+            try {
+                int length = value.length();
+                writeUleb128(length);
+                write(Mutf8.encode(value));
+                writeByte(0);
+            } catch (UTFDataFormatException e) {
+                throw new AssertionError();
+            }
+        }
+
+        public void writeTypeList(TypeList typeList) {
+            short[] types = typeList.getTypes();
+            writeInt(types.length);
+            for (short type : types) {
+                writeShort(type);
+            }
+            alignToFourBytesWithZeroFill();
+        }
+
+        /**
+         * Returns the number of bytes remaining in this section.
+         */
+        public int remaining() {
+            return data.remaining();
+        }
+
+        /**
+         * Returns the number of bytes used by this section.
+         */
+        public int used () {
+            return data.position() - initialPosition;
+        }
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/DexException.java b/dex/src/main/java/com/android/dex/DexException.java
new file mode 100644
index 0000000..a30a46f
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/DexException.java
@@ -0,0 +1,33 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ExceptionWithContext;
+
+/**
+ * Thrown when there's a format problem reading, writing, or generally
+ * processing a dex file.
+ */
+public final class DexException extends ExceptionWithContext {
+    public DexException(String message) {
+        super(message);
+    }
+
+    public DexException(Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/DexFormat.java b/dex/src/main/java/com/android/dex/DexFormat.java
new file mode 100644
index 0000000..85941fd
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/DexFormat.java
@@ -0,0 +1,98 @@
+/*
+ * 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 com.android.dex;
+
+/**
+ * Constants that show up in and are otherwise related to {@code .dex}
+ * files, and helper methods for same.
+ */
+public final class DexFormat {
+    private DexFormat() {}
+
+    /**
+     * API level to target in order to produce the most modern file
+     * format
+     */
+    public static final int API_CURRENT = 14;
+
+    /** API level to target in order to suppress extended opcode usage */
+    public static final int API_NO_EXTENDED_OPCODES = 13;
+
+    /**
+     * file name of the primary {@code .dex} file inside an
+     * application or library {@code .jar} file
+     */
+    public static final String DEX_IN_JAR_NAME = "classes.dex";
+
+    /** common prefix for all dex file "magic numbers" */
+    public static final String MAGIC_PREFIX = "dex\n";
+
+    /** common suffix for all dex file "magic numbers" */
+    public static final String MAGIC_SUFFIX = "\0";
+
+    /** dex file version number for the current format variant */
+    public static final String VERSION_CURRENT = "036";
+
+    /** dex file version number for API level 13 and earlier */
+    public static final String VERSION_FOR_API_13 = "035";
+
+    /**
+     * value used to indicate endianness of file contents
+     */
+    public static final int ENDIAN_TAG = 0x12345678;
+
+    /**
+     * Returns the API level corresponding to the given magic number,
+     * or {@code -1} if the given array is not a well-formed dex file
+     * magic number.
+     */
+    public static int magicToApi(byte[] magic) {
+        if (magic.length != 8) {
+            return -1;
+        }
+
+        if ((magic[0] != 'd') || (magic[1] != 'e') || (magic[2] != 'x') || (magic[3] != '\n') ||
+                (magic[7] != '\0')) {
+            return -1;
+        }
+
+        String version = "" + ((char) magic[4]) + ((char) magic[5]) +((char) magic[6]);
+
+        if (version.equals(VERSION_CURRENT)) {
+            return API_CURRENT;
+        } else if (version.equals(VERSION_FOR_API_13)) {
+            return 13;
+        }
+
+        return -1;
+    }
+
+    /**
+     * Returns the magic number corresponding to the given target API level.
+     */
+    public static String apiToMagic(int targetApiLevel) {
+        String version;
+
+        if (targetApiLevel >= API_CURRENT) {
+            version = VERSION_CURRENT;
+        } else {
+            version = VERSION_FOR_API_13;
+        }
+
+        return MAGIC_PREFIX + version + MAGIC_SUFFIX;
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/EncodedValue.java b/dex/src/main/java/com/android/dex/EncodedValue.java
new file mode 100644
index 0000000..8d0c3ad
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/EncodedValue.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteArrayByteInput;
+import com.android.dex.util.ByteInput;
+
+/**
+ * An encoded value or array.
+ */
+public final class EncodedValue implements Comparable<EncodedValue> {
+    private final byte[] data;
+
+    public EncodedValue(byte[] data) {
+        this.data = data;
+    }
+
+    public ByteInput asByteInput() {
+        return new ByteArrayByteInput(data);
+    }
+
+    public byte[] getBytes() {
+        return data;
+    }
+
+    public void writeTo(Dex.Section out) {
+        out.write(data);
+    }
+
+    @Override public int compareTo(EncodedValue other) {
+        int size = Math.min(data.length, other.data.length);
+        for (int i = 0; i < size; i++) {
+            if (data[i] != other.data[i]) {
+                return (data[i] & 0xff) - (other.data[i] & 0xff);
+            }
+        }
+        return data.length - other.data.length;
+    }
+
+    @Override public String toString() {
+        return Integer.toHexString(data[0] & 0xff) + "...(" + data.length + ")";
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/EncodedValueCodec.java b/dex/src/main/java/com/android/dex/EncodedValueCodec.java
new file mode 100644
index 0000000..7fc1724
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/EncodedValueCodec.java
@@ -0,0 +1,187 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteInput;
+import com.android.dex.util.ByteOutput;
+
+/**
+ * Read and write {@code encoded_value} primitives.
+ */
+public final class EncodedValueCodec {
+    private EncodedValueCodec() {
+    }
+
+    /**
+     * Writes a signed integral to {@code out}.
+     */
+    public static void writeSignedIntegralValue(ByteOutput out, int type, long value) {
+        /*
+         * Figure out how many bits are needed to represent the value,
+         * including a sign bit: The bit count is subtracted from 65
+         * and not 64 to account for the sign bit. The xor operation
+         * has the effect of leaving non-negative values alone and
+         * unary complementing negative values (so that a leading zero
+         * count always returns a useful number for our present
+         * purpose).
+         */
+        int requiredBits = 65 - Long.numberOfLeadingZeros(value ^ (value >> 63));
+
+        // Round up the requiredBits to a number of bytes.
+        int requiredBytes = (requiredBits + 0x07) >> 3;
+
+        /*
+         * Write the header byte, which includes the type and
+         * requiredBytes - 1.
+         */
+        out.writeByte(type | ((requiredBytes - 1) << 5));
+
+        // Write the value, per se.
+        while (requiredBytes > 0) {
+            out.writeByte((byte) value);
+            value >>= 8;
+            requiredBytes--;
+        }
+    }
+
+    /**
+     * Writes an unsigned integral to {@code out}.
+     */
+    public static void writeUnsignedIntegralValue(ByteOutput out, int type, long value) {
+        // Figure out how many bits are needed to represent the value.
+        int requiredBits = 64 - Long.numberOfLeadingZeros(value);
+        if (requiredBits == 0) {
+            requiredBits = 1;
+        }
+
+        // Round up the requiredBits to a number of bytes.
+        int requiredBytes = (requiredBits + 0x07) >> 3;
+
+        /*
+         * Write the header byte, which includes the type and
+         * requiredBytes - 1.
+         */
+        out.writeByte(type | ((requiredBytes - 1) << 5));
+
+        // Write the value, per se.
+        while (requiredBytes > 0) {
+            out.writeByte((byte) value);
+            value >>= 8;
+            requiredBytes--;
+        }
+    }
+
+    /**
+     * Writes a right-zero-extended value to {@code out}.
+     */
+    public static void writeRightZeroExtendedValue(ByteOutput out, int type, long value) {
+        // Figure out how many bits are needed to represent the value.
+        int requiredBits = 64 - Long.numberOfTrailingZeros(value);
+        if (requiredBits == 0) {
+            requiredBits = 1;
+        }
+
+        // Round up the requiredBits to a number of bytes.
+        int requiredBytes = (requiredBits + 0x07) >> 3;
+
+        // Scootch the first bits to be written down to the low-order bits.
+        value >>= 64 - (requiredBytes * 8);
+
+        /*
+         * Write the header byte, which includes the type and
+         * requiredBytes - 1.
+         */
+        out.writeByte(type | ((requiredBytes - 1) << 5));
+
+        // Write the value, per se.
+        while (requiredBytes > 0) {
+            out.writeByte((byte) value);
+            value >>= 8;
+            requiredBytes--;
+        }
+    }
+
+    /**
+     * Read a signed integer.
+     *
+     * @param zwidth byte count minus one
+     */
+    public static int readSignedInt(ByteInput in, int zwidth) {
+        int result = 0;
+        for (int i = zwidth; i >= 0; i--) {
+            result = (result >>> 8) | ((in.readByte() & 0xff) << 24);
+        }
+        result >>= (3 - zwidth) * 8;
+        return result;
+    }
+
+    /**
+     * Read an unsigned integer.
+     *
+     * @param zwidth byte count minus one
+     * @param fillOnRight true to zero fill on the right; false on the left
+     */
+    public static int readUnsignedInt(ByteInput in, int zwidth, boolean fillOnRight) {
+        int result = 0;
+        if (!fillOnRight) {
+            for (int i = zwidth; i >= 0; i--) {
+                result = (result >>> 8) | ((in.readByte() & 0xff) << 24);
+            }
+            result >>>= (3 - zwidth) * 8;
+        } else {
+            for (int i = zwidth; i >= 0; i--) {
+                result = (result >>> 8) | ((in.readByte() & 0xff) << 24);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Read a signed long.
+     *
+     * @param zwidth byte count minus one
+     */
+    public static long readSignedLong(ByteInput in, int zwidth) {
+        long result = 0;
+        for (int i = zwidth; i >= 0; i--) {
+            result = (result >>> 8) | ((in.readByte() & 0xffL) << 56);
+        }
+        result >>= (7 - zwidth) * 8;
+        return result;
+    }
+
+    /**
+     * Read an unsigned long.
+     *
+     * @param zwidth byte count minus one
+     * @param fillOnRight true to zero fill on the right; false on the left
+     */
+    public static long readUnsignedLong(ByteInput in, int zwidth, boolean fillOnRight) {
+        long result = 0;
+        if (!fillOnRight) {
+            for (int i = zwidth; i >= 0; i--) {
+                result = (result >>> 8) | ((in.readByte() & 0xffL) << 56);
+            }
+            result >>>= (7 - zwidth) * 8;
+        } else {
+            for (int i = zwidth; i >= 0; i--) {
+                result = (result >>> 8) | ((in.readByte() & 0xffL) << 56);
+            }
+        }
+        return result;
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/EncodedValueReader.java b/dex/src/main/java/com/android/dex/EncodedValueReader.java
new file mode 100644
index 0000000..6f60538
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/EncodedValueReader.java
@@ -0,0 +1,287 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteInput;
+
+/**
+ * Pull parser for encoded values.
+ */
+public final class EncodedValueReader {
+    public static final int ENCODED_BYTE = 0x00;
+    public static final int ENCODED_SHORT = 0x02;
+    public static final int ENCODED_CHAR = 0x03;
+    public static final int ENCODED_INT = 0x04;
+    public static final int ENCODED_LONG = 0x06;
+    public static final int ENCODED_FLOAT = 0x10;
+    public static final int ENCODED_DOUBLE = 0x11;
+    public static final int ENCODED_STRING = 0x17;
+    public static final int ENCODED_TYPE = 0x18;
+    public static final int ENCODED_FIELD = 0x19;
+    public static final int ENCODED_ENUM = 0x1b;
+    public static final int ENCODED_METHOD = 0x1a;
+    public static final int ENCODED_ARRAY = 0x1c;
+    public static final int ENCODED_ANNOTATION = 0x1d;
+    public static final int ENCODED_NULL = 0x1e;
+    public static final int ENCODED_BOOLEAN = 0x1f;
+
+    /** placeholder type if the type is not yet known */
+    private static final int MUST_READ = -1;
+
+    protected final ByteInput in;
+    private int type = MUST_READ;
+    private int annotationType;
+    private int arg;
+
+    public EncodedValueReader(ByteInput in) {
+        this.in = in;
+    }
+
+    public EncodedValueReader(EncodedValue in) {
+        this(in.asByteInput());
+    }
+
+    /**
+     * Creates a new encoded value reader whose only value is the specified
+     * known type. This is useful for encoded values without a type prefix,
+     * such as class_def_item's encoded_array or annotation_item's
+     * encoded_annotation.
+     */
+    public EncodedValueReader(ByteInput in, int knownType) {
+        this.in = in;
+        this.type = knownType;
+    }
+
+    public EncodedValueReader(EncodedValue in, int knownType) {
+        this(in.asByteInput(), knownType);
+    }
+
+    /**
+     * Returns the type of the next value to read.
+     */
+    public int peek() {
+        if (type == MUST_READ) {
+            int argAndType = in.readByte() & 0xff;
+            type = argAndType & 0x1f;
+            arg = (argAndType & 0xe0) >> 5;
+        }
+        return type;
+    }
+
+    /**
+     * Begins reading the elements of an array, returning the array's size. The
+     * caller must follow up by calling a read method for each element in the
+     * array. For example, this reads a byte array: <pre>   {@code
+     *   int arraySize = readArray();
+     *   for (int i = 0, i < arraySize; i++) {
+     *     readByte();
+     *   }
+     * }</pre>
+     */
+    public int readArray() {
+        checkType(ENCODED_ARRAY);
+        type = MUST_READ;
+        return Leb128.readUnsignedLeb128(in);
+    }
+
+    /**
+     * Begins reading the fields of an annotation, returning the number of
+     * fields. The caller must follow up by making alternating calls to {@link
+     * #readAnnotationName()} and another read method. For example, this reads
+     * an annotation whose fields are all bytes: <pre>   {@code
+     *   int fieldCount = readAnnotation();
+     *   int annotationType = getAnnotationType();
+     *   for (int i = 0; i < fieldCount; i++) {
+     *       readAnnotationName();
+     *       readByte();
+     *   }
+     * }</pre>
+     */
+    public int readAnnotation() {
+        checkType(ENCODED_ANNOTATION);
+        type = MUST_READ;
+        annotationType = Leb128.readUnsignedLeb128(in);
+        return Leb128.readUnsignedLeb128(in);
+    }
+
+    /**
+     * Returns the type of the annotation just returned by {@link
+     * #readAnnotation()}. This method's value is undefined unless the most
+     * recent call was to {@link #readAnnotation()}.
+     */
+    public int getAnnotationType() {
+        return annotationType;
+    }
+
+    public int readAnnotationName() {
+        return Leb128.readUnsignedLeb128(in);
+    }
+
+    public byte readByte() {
+        checkType(ENCODED_BYTE);
+        type = MUST_READ;
+        return (byte) EncodedValueCodec.readSignedInt(in, arg);
+    }
+
+    public short readShort() {
+        checkType(ENCODED_SHORT);
+        type = MUST_READ;
+        return (short) EncodedValueCodec.readSignedInt(in, arg);
+    }
+
+    public char readChar() {
+        checkType(ENCODED_CHAR);
+        type = MUST_READ;
+        return (char) EncodedValueCodec.readUnsignedInt(in, arg, false);
+    }
+
+    public int readInt() {
+        checkType(ENCODED_INT);
+        type = MUST_READ;
+        return EncodedValueCodec.readSignedInt(in, arg);
+    }
+
+    public long readLong() {
+        checkType(ENCODED_LONG);
+        type = MUST_READ;
+        return EncodedValueCodec.readSignedLong(in, arg);
+    }
+
+    public float readFloat() {
+        checkType(ENCODED_FLOAT);
+        type = MUST_READ;
+        return Float.intBitsToFloat(EncodedValueCodec.readUnsignedInt(in, arg, true));
+    }
+
+    public double readDouble() {
+        checkType(ENCODED_DOUBLE);
+        type = MUST_READ;
+        return Double.longBitsToDouble(EncodedValueCodec.readUnsignedLong(in, arg, true));
+    }
+
+    public int readString() {
+        checkType(ENCODED_STRING);
+        type = MUST_READ;
+        return EncodedValueCodec.readUnsignedInt(in, arg, false);
+    }
+
+    public int readType() {
+        checkType(ENCODED_TYPE);
+        type = MUST_READ;
+        return EncodedValueCodec.readUnsignedInt(in, arg, false);
+    }
+
+    public int readField() {
+        checkType(ENCODED_FIELD);
+        type = MUST_READ;
+        return EncodedValueCodec.readUnsignedInt(in, arg, false);
+    }
+
+    public int readEnum() {
+        checkType(ENCODED_ENUM);
+        type = MUST_READ;
+        return EncodedValueCodec.readUnsignedInt(in, arg, false);
+    }
+
+    public int readMethod() {
+        checkType(ENCODED_METHOD);
+        type = MUST_READ;
+        return EncodedValueCodec.readUnsignedInt(in, arg, false);
+    }
+
+    public void readNull() {
+        checkType(ENCODED_NULL);
+        type = MUST_READ;
+    }
+
+    public boolean readBoolean() {
+        checkType(ENCODED_BOOLEAN);
+        type = MUST_READ;
+        return arg != 0;
+    }
+
+    /**
+     * Skips a single value, including its nested values if it is an array or
+     * annotation.
+     */
+    public void skipValue() {
+        switch (peek()) {
+        case ENCODED_BYTE:
+            readByte();
+            break;
+        case ENCODED_SHORT:
+            readShort();
+            break;
+        case ENCODED_CHAR:
+            readChar();
+            break;
+        case ENCODED_INT:
+            readInt();
+            break;
+        case ENCODED_LONG:
+            readLong();
+            break;
+        case ENCODED_FLOAT:
+            readFloat();
+            break;
+        case ENCODED_DOUBLE:
+            readDouble();
+            break;
+        case ENCODED_STRING:
+            readString();
+            break;
+        case ENCODED_TYPE:
+            readType();
+            break;
+        case ENCODED_FIELD:
+            readField();
+            break;
+        case ENCODED_ENUM:
+            readEnum();
+            break;
+        case ENCODED_METHOD:
+            readMethod();
+            break;
+        case ENCODED_ARRAY:
+            for (int i = 0, size = readArray(); i < size; i++) {
+                skipValue();
+            }
+            break;
+        case ENCODED_ANNOTATION:
+            for (int i = 0, size = readAnnotation(); i < size; i++) {
+                readAnnotationName();
+                skipValue();
+            }
+            break;
+        case ENCODED_NULL:
+            readNull();
+            break;
+        case ENCODED_BOOLEAN:
+            readBoolean();
+            break;
+        default:
+            throw new DexException("Unexpected type: " + Integer.toHexString(type));
+        }
+    }
+
+    private void checkType(int expected) {
+        if (peek() != expected) {
+            throw new IllegalStateException(
+                    String.format("Expected %x but was %x", expected, peek()));
+        }
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/FieldId.java b/dex/src/main/java/com/android/dex/FieldId.java
new file mode 100644
index 0000000..2f41708
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/FieldId.java
@@ -0,0 +1,68 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.Unsigned;
+
+public final class FieldId implements Comparable<FieldId> {
+    private final Dex dex;
+    private final int declaringClassIndex;
+    private final int typeIndex;
+    private final int nameIndex;
+
+    public FieldId(Dex dex, int declaringClassIndex, int typeIndex, int nameIndex) {
+        this.dex = dex;
+        this.declaringClassIndex = declaringClassIndex;
+        this.typeIndex = typeIndex;
+        this.nameIndex = nameIndex;
+    }
+
+    public int getDeclaringClassIndex() {
+        return declaringClassIndex;
+    }
+
+    public int getTypeIndex() {
+        return typeIndex;
+    }
+
+    public int getNameIndex() {
+        return nameIndex;
+    }
+
+    public int compareTo(FieldId other) {
+        if (declaringClassIndex != other.declaringClassIndex) {
+            return Unsigned.compare(declaringClassIndex, other.declaringClassIndex);
+        }
+        if (nameIndex != other.nameIndex) {
+            return Unsigned.compare(nameIndex, other.nameIndex);
+        }
+        return Unsigned.compare(typeIndex, other.typeIndex); // should always be 0
+    }
+
+    public void writeTo(Dex.Section out) {
+        out.writeUnsignedShort(declaringClassIndex);
+        out.writeUnsignedShort(typeIndex);
+        out.writeInt(nameIndex);
+    }
+
+    @Override public String toString() {
+        if (dex == null) {
+            return declaringClassIndex + " " + typeIndex + " " + nameIndex;
+        }
+        return dex.typeNames().get(typeIndex) + "." + dex.strings().get(nameIndex);
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/Leb128.java b/dex/src/main/java/com/android/dex/Leb128.java
new file mode 100644
index 0000000..1a82e38
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/Leb128.java
@@ -0,0 +1,161 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteInput;
+import com.android.dex.util.ByteOutput;
+
+/**
+ * Reads and writes DWARFv3 LEB 128 signed and unsigned integers. See DWARF v3
+ * section 7.6.
+ */
+public final class Leb128 {
+    private Leb128() {
+    }
+
+    /**
+     * Gets the number of bytes in the unsigned LEB128 encoding of the
+     * given value.
+     *
+     * @param value the value in question
+     * @return its write size, in bytes
+     */
+    public static int unsignedLeb128Size(int value) {
+        // TODO: This could be much cleverer.
+
+        int remaining = value >> 7;
+        int count = 0;
+
+        while (remaining != 0) {
+            remaining >>= 7;
+            count++;
+        }
+
+        return count + 1;
+    }
+
+    /**
+     * Gets the number of bytes in the signed LEB128 encoding of the
+     * given value.
+     *
+     * @param value the value in question
+     * @return its write size, in bytes
+     */
+    public static int signedLeb128Size(int value) {
+        // TODO: This could be much cleverer.
+
+        int remaining = value >> 7;
+        int count = 0;
+        boolean hasMore = true;
+        int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1;
+
+        while (hasMore) {
+            hasMore = (remaining != end)
+                || ((remaining & 1) != ((value >> 6) & 1));
+
+            value = remaining;
+            remaining >>= 7;
+            count++;
+        }
+
+        return count;
+    }
+
+    /**
+     * Reads an signed integer from {@code in}.
+     */
+    public static int readSignedLeb128(ByteInput in) {
+        int result = 0;
+        int cur;
+        int count = 0;
+        int signBits = -1;
+
+        do {
+            cur = in.readByte() & 0xff;
+            result |= (cur & 0x7f) << (count * 7);
+            signBits <<= 7;
+            count++;
+        } while (((cur & 0x80) == 0x80) && count < 5);
+
+        if ((cur & 0x80) == 0x80) {
+            throw new DexException("invalid LEB128 sequence");
+        }
+
+        // Sign extend if appropriate
+        if (((signBits >> 1) & result) != 0 ) {
+            result |= signBits;
+        }
+
+        return result;
+    }
+
+    /**
+     * Reads an unsigned integer from {@code in}.
+     */
+    public static int readUnsignedLeb128(ByteInput in) {
+        int result = 0;
+        int cur;
+        int count = 0;
+
+        do {
+            cur = in.readByte() & 0xff;
+            result |= (cur & 0x7f) << (count * 7);
+            count++;
+        } while (((cur & 0x80) == 0x80) && count < 5);
+
+        if ((cur & 0x80) == 0x80) {
+            throw new DexException("invalid LEB128 sequence");
+        }
+
+        return result;
+    }
+
+    /**
+     * Writes {@code value} as an unsigned integer to {@code out}, starting at
+     * {@code offset}. Returns the number of bytes written.
+     */
+    public static void writeUnsignedLeb128(ByteOutput out, int value) {
+        int remaining = value >>> 7;
+
+        while (remaining != 0) {
+            out.writeByte((byte) ((value & 0x7f) | 0x80));
+            value = remaining;
+            remaining >>>= 7;
+        }
+
+        out.writeByte((byte) (value & 0x7f));
+    }
+
+    /**
+     * Writes {@code value} as a signed integer to {@code out}, starting at
+     * {@code offset}. Returns the number of bytes written.
+     */
+    public static void writeSignedLeb128(ByteOutput out, int value) {
+        int remaining = value >> 7;
+        boolean hasMore = true;
+        int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1;
+
+        while (hasMore) {
+            hasMore = (remaining != end)
+                    || ((remaining & 1) != ((value >> 6) & 1));
+
+            out.writeByte((byte) ((value & 0x7f) | (hasMore ? 0x80 : 0)));
+            value = remaining;
+            remaining >>= 7;
+        }
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/MethodId.java b/dex/src/main/java/com/android/dex/MethodId.java
new file mode 100644
index 0000000..e518740
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/MethodId.java
@@ -0,0 +1,70 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.Unsigned;
+
+public final class MethodId implements Comparable<MethodId> {
+    private final Dex dex;
+    private final int declaringClassIndex;
+    private final int protoIndex;
+    private final int nameIndex;
+
+    public MethodId(Dex dex, int declaringClassIndex, int protoIndex, int nameIndex) {
+        this.dex = dex;
+        this.declaringClassIndex = declaringClassIndex;
+        this.protoIndex = protoIndex;
+        this.nameIndex = nameIndex;
+    }
+
+    public int getDeclaringClassIndex() {
+        return declaringClassIndex;
+    }
+
+    public int getProtoIndex() {
+        return protoIndex;
+    }
+
+    public int getNameIndex() {
+        return nameIndex;
+    }
+
+    public int compareTo(MethodId other) {
+        if (declaringClassIndex != other.declaringClassIndex) {
+            return Unsigned.compare(declaringClassIndex, other.declaringClassIndex);
+        }
+        if (nameIndex != other.nameIndex) {
+            return Unsigned.compare(nameIndex, other.nameIndex);
+        }
+        return Unsigned.compare(protoIndex, other.protoIndex);
+    }
+
+    public void writeTo(Dex.Section out) {
+        out.writeUnsignedShort(declaringClassIndex);
+        out.writeUnsignedShort(protoIndex);
+        out.writeInt(nameIndex);
+    }
+
+    @Override public String toString() {
+        if (dex == null) {
+            return declaringClassIndex + " " + protoIndex + " " + nameIndex;
+        }
+        return dex.typeNames().get(declaringClassIndex)
+                + "." + dex.strings().get(nameIndex)
+                + dex.readTypeList(dex.protoIds().get(protoIndex).getParametersOffset());
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/Mutf8.java b/dex/src/main/java/com/android/dex/Mutf8.java
new file mode 100644
index 0000000..c64da33
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/Mutf8.java
@@ -0,0 +1,115 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteInput;
+import java.io.UTFDataFormatException;
+
+/**
+ * Modified UTF-8 as described in the dex file format spec.
+ *
+ * <p>Derived from libcore's MUTF-8 encoder at java.nio.charset.ModifiedUtf8.
+ */
+public final class Mutf8 {
+    private Mutf8() {}
+
+    /**
+     * Decodes bytes from {@code in} into {@code out} until a delimiter 0x00 is
+     * encountered. Returns a new string containing the decoded characters.
+     */
+    public static String decode(ByteInput in, char[] out) throws UTFDataFormatException {
+        int s = 0;
+        while (true) {
+            char a = (char) (in.readByte() & 0xff);
+            if (a == 0) {
+                return new String(out, 0, s);
+            }
+            out[s] = a;
+            if (a < '\u0080') {
+                s++;
+            } else if ((a & 0xe0) == 0xc0) {
+                int b = in.readByte() & 0xff;
+                if ((b & 0xC0) != 0x80) {
+                    throw new UTFDataFormatException("bad second byte");
+                }
+                out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+            } else if ((a & 0xf0) == 0xe0) {
+                int b = in.readByte() & 0xff;
+                int c = in.readByte() & 0xff;
+                if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) {
+                    throw new UTFDataFormatException("bad second or third byte");
+                }
+                out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
+            } else {
+                throw new UTFDataFormatException("bad byte");
+            }
+        }
+    }
+
+    /**
+     * Returns the number of bytes the modified UTF8 representation of 's' would take.
+     */
+    private static long countBytes(String s, boolean shortLength) throws UTFDataFormatException {
+        long result = 0;
+        final int length = s.length();
+        for (int i = 0; i < length; ++i) {
+            char ch = s.charAt(i);
+            if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
+                ++result;
+            } else if (ch <= 2047) {
+                result += 2;
+            } else {
+                result += 3;
+            }
+            if (shortLength && result > 65535) {
+                throw new UTFDataFormatException("String more than 65535 UTF bytes long");
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Encodes the modified UTF-8 bytes corresponding to {@code s} into  {@code
+     * dst}, starting at {@code offset}.
+     */
+    public static void encode(byte[] dst, int offset, String s) {
+        final int length = s.length();
+        for (int i = 0; i < length; i++) {
+            char ch = s.charAt(i);
+            if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
+                dst[offset++] = (byte) ch;
+            } else if (ch <= 2047) {
+                dst[offset++] = (byte) (0xc0 | (0x1f & (ch >> 6)));
+                dst[offset++] = (byte) (0x80 | (0x3f & ch));
+            } else {
+                dst[offset++] = (byte) (0xe0 | (0x0f & (ch >> 12)));
+                dst[offset++] = (byte) (0x80 | (0x3f & (ch >> 6)));
+                dst[offset++] = (byte) (0x80 | (0x3f & ch));
+            }
+        }
+    }
+
+    /**
+     * Returns an array containing the <i>modified UTF-8</i> form of {@code s}.
+     */
+    public static byte[] encode(String s) throws UTFDataFormatException {
+        int utfCount = (int) countBytes(s, true);
+        byte[] result = new byte[utfCount];
+        encode(result, 0, s);
+        return result;
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/ProtoId.java b/dex/src/main/java/com/android/dex/ProtoId.java
new file mode 100644
index 0000000..9d9f484
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/ProtoId.java
@@ -0,0 +1,68 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.Unsigned;
+
+public final class ProtoId implements Comparable<ProtoId> {
+    private final Dex dex;
+    private final int shortyIndex;
+    private final int returnTypeIndex;
+    private final int parametersOffset;
+
+    public ProtoId(Dex dex, int shortyIndex, int returnTypeIndex, int parametersOffset) {
+        this.dex = dex;
+        this.shortyIndex = shortyIndex;
+        this.returnTypeIndex = returnTypeIndex;
+        this.parametersOffset = parametersOffset;
+    }
+
+    public int compareTo(ProtoId other) {
+        if (returnTypeIndex != other.returnTypeIndex) {
+            return Unsigned.compare(returnTypeIndex, other.returnTypeIndex);
+        }
+        return Unsigned.compare(parametersOffset, other.parametersOffset);
+    }
+
+    public int getShortyIndex() {
+        return shortyIndex;
+    }
+
+    public int getReturnTypeIndex() {
+        return returnTypeIndex;
+    }
+
+    public int getParametersOffset() {
+        return parametersOffset;
+    }
+
+    public void writeTo(Dex.Section out) {
+        out.writeInt(shortyIndex);
+        out.writeInt(returnTypeIndex);
+        out.writeInt(parametersOffset);
+    }
+
+    @Override public String toString() {
+        if (dex == null) {
+            return shortyIndex + " " + returnTypeIndex + " " + parametersOffset;
+        }
+
+        return dex.strings().get(shortyIndex)
+                + ": " + dex.typeNames().get(returnTypeIndex)
+                + " " + dex.readTypeList(parametersOffset);
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/SizeOf.java b/dex/src/main/java/com/android/dex/SizeOf.java
new file mode 100644
index 0000000..65fab56
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/SizeOf.java
@@ -0,0 +1,110 @@
+/*
+ * 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 com.android.dex;
+
+public final class SizeOf {
+    private SizeOf() {}
+
+    public static final int UBYTE = 1;
+    public static final int USHORT = 2;
+    public static final int UINT = 4;
+
+    public static final int SIGNATURE = UBYTE * 20;
+
+    /**
+     * magic ubyte[8]
+     * checksum uint
+     * signature ubyte[20]
+     * file_size uint
+     * header_size uint
+     * endian_tag uint
+     * link_size uint
+     * link_off uint
+     * map_off uint
+     * string_ids_size uint
+     * string_ids_off uint
+     * type_ids_size uint
+     * type_ids_off uint
+     * proto_ids_size uint
+     * proto_ids_off uint
+     * field_ids_size uint
+     * field_ids_off uint
+     * method_ids_size uint
+     * method_ids_off uint
+     * class_defs_size uint
+     * class_defs_off uint
+     * data_size uint
+     * data_off uint
+     */
+    public static final int HEADER_ITEM = (8 * UBYTE) + UINT + SIGNATURE + (20 * UINT); // 0x70
+
+    /**
+     * string_data_off uint
+     */
+    public static final int STRING_ID_ITEM = UINT;
+
+    /**
+     * descriptor_idx uint
+     */
+    public static final int TYPE_ID_ITEM = UINT;
+
+    /**
+     * type_idx ushort
+     */
+    public static final int TYPE_ITEM = USHORT;
+
+    /**
+     * shorty_idx uint
+     * return_type_idx uint
+     * return_type_idx uint
+     */
+    public static final int PROTO_ID_ITEM = UINT + UINT + UINT;
+
+    /**
+     * class_idx ushort
+     * type_idx/proto_idx ushort
+     * name_idx uint
+     */
+    public static final int MEMBER_ID_ITEM = USHORT + USHORT + UINT;
+
+    /**
+     * class_idx uint
+     * access_flags uint
+     * superclass_idx uint
+     * interfaces_off uint
+     * source_file_idx uint
+     * annotations_off uint
+     * class_data_off uint
+     * static_values_off uint
+     */
+    public static final int CLASS_DEF_ITEM = 8 * UINT;
+
+    /**
+     * type ushort
+     * unused ushort
+     * size uint
+     * offset uint
+     */
+    public static final int MAP_ITEM = USHORT + USHORT + UINT + UINT;
+
+    /**
+     * start_addr uint
+     * insn_count ushort
+     * handler_off ushort
+     */
+    public static final int TRY_ITEM = UINT + USHORT + USHORT;
+}
diff --git a/dex/src/main/java/com/android/dex/TableOfContents.java b/dex/src/main/java/com/android/dex/TableOfContents.java
new file mode 100644
index 0000000..d1b87ac
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/TableOfContents.java
@@ -0,0 +1,236 @@
+/*
+ * 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 com.android.dex;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+/**
+ * The file header and map.
+ */
+public final class TableOfContents {
+
+    /*
+     * TODO: factor out ID constants.
+     */
+
+    public final Section header = new Section(0x0000);
+    public final Section stringIds = new Section(0x0001);
+    public final Section typeIds = new Section(0x0002);
+    public final Section protoIds = new Section(0x0003);
+    public final Section fieldIds = new Section(0x0004);
+    public final Section methodIds = new Section(0x0005);
+    public final Section classDefs = new Section(0x0006);
+    public final Section mapList = new Section(0x1000);
+    public final Section typeLists = new Section(0x1001);
+    public final Section annotationSetRefLists = new Section(0x1002);
+    public final Section annotationSets = new Section(0x1003);
+    public final Section classDatas = new Section(0x2000);
+    public final Section codes = new Section(0x2001);
+    public final Section stringDatas = new Section(0x2002);
+    public final Section debugInfos = new Section(0x2003);
+    public final Section annotations = new Section(0x2004);
+    public final Section encodedArrays = new Section(0x2005);
+    public final Section annotationsDirectories = new Section(0x2006);
+    public final Section[] sections = {
+            header, stringIds, typeIds, protoIds, fieldIds, methodIds, classDefs, mapList,
+            typeLists, annotationSetRefLists, annotationSets, classDatas, codes, stringDatas,
+            debugInfos, annotations, encodedArrays, annotationsDirectories
+    };
+
+    public int checksum;
+    public byte[] signature;
+    public int fileSize;
+    public int linkSize;
+    public int linkOff;
+    public int dataSize;
+    public int dataOff;
+
+    public TableOfContents() {
+        signature = new byte[20];
+    }
+
+    public void readFrom(Dex dex) throws IOException {
+        readHeader(dex.open(0));
+        readMap(dex.open(mapList.off));
+        computeSizesFromOffsets();
+    }
+
+    private void readHeader(Dex.Section headerIn) throws UnsupportedEncodingException {
+        byte[] magic = headerIn.readByteArray(8);
+        int apiTarget = DexFormat.magicToApi(magic);
+
+        if (apiTarget != DexFormat.API_NO_EXTENDED_OPCODES) {
+            throw new DexException("Unexpected magic: " + Arrays.toString(magic));
+        }
+
+        checksum = headerIn.readInt();
+        signature = headerIn.readByteArray(20);
+        fileSize = headerIn.readInt();
+        int headerSize = headerIn.readInt();
+        if (headerSize != SizeOf.HEADER_ITEM) {
+            throw new DexException("Unexpected header: 0x" + Integer.toHexString(headerSize));
+        }
+        int endianTag = headerIn.readInt();
+        if (endianTag != DexFormat.ENDIAN_TAG) {
+            throw new DexException("Unexpected endian tag: 0x" + Integer.toHexString(endianTag));
+        }
+        linkSize = headerIn.readInt();
+        linkOff = headerIn.readInt();
+        mapList.off = headerIn.readInt();
+        if (mapList.off == 0) {
+            throw new DexException("Cannot merge dex files that do not contain a map");
+        }
+        stringIds.size = headerIn.readInt();
+        stringIds.off = headerIn.readInt();
+        typeIds.size = headerIn.readInt();
+        typeIds.off = headerIn.readInt();
+        protoIds.size = headerIn.readInt();
+        protoIds.off = headerIn.readInt();
+        fieldIds.size = headerIn.readInt();
+        fieldIds.off = headerIn.readInt();
+        methodIds.size = headerIn.readInt();
+        methodIds.off = headerIn.readInt();
+        classDefs.size = headerIn.readInt();
+        classDefs.off = headerIn.readInt();
+        dataSize = headerIn.readInt();
+        dataOff = headerIn.readInt();
+    }
+
+    private void readMap(Dex.Section in) throws IOException {
+        int mapSize = in.readInt();
+        Section previous = null;
+        for (int i = 0; i < mapSize; i++) {
+            short type = in.readShort();
+            in.readShort(); // unused
+            Section section = getSection(type);
+            int size = in.readInt();
+            int offset = in.readInt();
+
+            if ((section.size != 0 && section.size != size)
+                    || (section.off != -1 && section.off != offset)) {
+                throw new DexException("Unexpected map value for 0x" + Integer.toHexString(type));
+            }
+
+            section.size = size;
+            section.off = offset;
+
+            if (previous != null && previous.off > section.off) {
+                throw new DexException("Map is unsorted at " + previous + ", " + section);
+            }
+
+            previous = section;
+        }
+        Arrays.sort(sections);
+    }
+
+    public void computeSizesFromOffsets() {
+        int end = dataOff + dataSize;
+        for (int i = sections.length - 1; i >= 0; i--) {
+            Section section = sections[i];
+            if (section.off == -1) {
+                continue;
+            }
+            if (section.off > end) {
+                throw new DexException("Map is unsorted at " + section);
+            }
+            section.byteCount = end - section.off;
+            end = section.off;
+        }
+    }
+
+    private Section getSection(short type) {
+        for (Section section : sections) {
+            if (section.type == type) {
+                return section;
+            }
+        }
+        throw new IllegalArgumentException("No such map item: " + type);
+    }
+
+    public void writeHeader(Dex.Section out) throws IOException {
+        out.write(DexFormat.apiToMagic(DexFormat.API_NO_EXTENDED_OPCODES).getBytes("UTF-8"));
+        out.writeInt(checksum);
+        out.write(signature);
+        out.writeInt(fileSize);
+        out.writeInt(SizeOf.HEADER_ITEM);
+        out.writeInt(DexFormat.ENDIAN_TAG);
+        out.writeInt(linkSize);
+        out.writeInt(linkOff);
+        out.writeInt(mapList.off);
+        out.writeInt(stringIds.size);
+        out.writeInt(stringIds.off);
+        out.writeInt(typeIds.size);
+        out.writeInt(typeIds.off);
+        out.writeInt(protoIds.size);
+        out.writeInt(protoIds.off);
+        out.writeInt(fieldIds.size);
+        out.writeInt(fieldIds.off);
+        out.writeInt(methodIds.size);
+        out.writeInt(methodIds.off);
+        out.writeInt(classDefs.size);
+        out.writeInt(classDefs.off);
+        out.writeInt(dataSize);
+        out.writeInt(dataOff);
+    }
+
+    public void writeMap(Dex.Section out) throws IOException {
+        int count = 0;
+        for (Section section : sections) {
+            if (section.exists()) {
+                count++;
+            }
+        }
+
+        out.writeInt(count);
+        for (Section section : sections) {
+            if (section.exists()) {
+                out.writeShort(section.type);
+                out.writeShort((short) 0);
+                out.writeInt(section.size);
+                out.writeInt(section.off);
+            }
+        }
+    }
+
+    public static class Section implements Comparable<Section> {
+        public final short type;
+        public int size = 0;
+        public int off = -1;
+        public int byteCount = 0;
+
+        public Section(int type) {
+            this.type = (short) type;
+        }
+
+        public boolean exists() {
+            return size > 0;
+        }
+
+        public int compareTo(Section section) {
+            if (off != section.off) {
+                return off < section.off ? -1 : 1;
+            }
+            return 0;
+        }
+
+        @Override public String toString() {
+            return String.format("Section[type=%#x,off=%#x,size=%#x]", type, off, size);
+        }
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/TypeList.java b/dex/src/main/java/com/android/dex/TypeList.java
new file mode 100644
index 0000000..6e321fb
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/TypeList.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.Unsigned;
+
+public final class TypeList implements Comparable<TypeList> {
+
+    public static final TypeList EMPTY = new TypeList(null, new short[0]);
+
+    private final Dex dex;
+    private final short[] types;
+
+    public TypeList(Dex dex, short[] types) {
+        this.dex = dex;
+        this.types = types;
+    }
+
+    public short[] getTypes() {
+        return types;
+    }
+
+    @Override public int compareTo(TypeList other) {
+        for (int i = 0; i < types.length && i < other.types.length; i++) {
+            if (types[i] != other.types[i]) {
+                return Unsigned.compare(types[i], other.types[i]);
+            }
+        }
+        return Unsigned.compare(types.length, other.types.length);
+    }
+
+    @Override public String toString() {
+        StringBuilder result = new StringBuilder();
+        result.append("(");
+        for (int i = 0, typesLength = types.length; i < typesLength; i++) {
+            result.append(dex != null ? dex.typeNames().get(types[i]) : types[i]);
+        }
+        result.append(")");
+        return result.toString();
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java b/dex/src/main/java/com/android/dex/util/ByteArrayByteInput.java
similarity index 61%
copy from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java
copy to dex/src/main/java/com/android/dex/util/ByteArrayByteInput.java
index 8b74514..889a936 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java
+++ b/dex/src/main/java/com/android/dex/util/ByteArrayByteInput.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -14,16 +14,18 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package com.android.dex.util;
 
-// public for testing by CertPinManagerTest
-public class PinEntryException extends Exception {
+public final class ByteArrayByteInput implements ByteInput {
 
-    PinEntryException() {
+    private final byte[] bytes;
+    private int position;
+
+    public ByteArrayByteInput(byte... bytes) {
+        this.bytes = bytes;
     }
 
-    PinEntryException(String msg) {
-        super(msg);
+    @Override public byte readByte() {
+        return bytes[position++];
     }
 }
-
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java b/dex/src/main/java/com/android/dex/util/ByteInput.java
similarity index 66%
copy from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
copy to dex/src/main/java/com/android/dex/util/ByteInput.java
index 548e9c5..f1a7196 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
+++ b/dex/src/main/java/com/android/dex/util/ByteInput.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,8 +14,17 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package com.android.dex.util;
 
-public interface OpenSSLKeyHolder {
-    public OpenSSLKey getOpenSSLKey();
+/**
+ * A byte source.
+ */
+public interface ByteInput {
+
+    /**
+     * Returns a byte.
+     *
+     * @throws IndexOutOfBoundsException if all bytes have been read.
+     */
+    byte readByte();
 }
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java b/dex/src/main/java/com/android/dex/util/ByteOutput.java
similarity index 66%
copy from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
copy to dex/src/main/java/com/android/dex/util/ByteOutput.java
index 548e9c5..eb77040 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
+++ b/dex/src/main/java/com/android/dex/util/ByteOutput.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,8 +14,17 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package com.android.dex.util;
 
-public interface OpenSSLKeyHolder {
-    public OpenSSLKey getOpenSSLKey();
+/**
+ * A byte sink.
+ */
+public interface ByteOutput {
+
+    /**
+     * Writes a byte.
+     *
+     * @throws IndexOutOfBoundsException if all bytes have been written.
+     */
+    void writeByte(int i);
 }
diff --git a/dex/src/main/java/com/android/dex/util/ExceptionWithContext.java b/dex/src/main/java/com/android/dex/util/ExceptionWithContext.java
new file mode 100644
index 0000000..5dfd954
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/util/ExceptionWithContext.java
@@ -0,0 +1,148 @@
+/*
+ * 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 com.android.dex.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * Exception which carries around structured context.
+ */
+public class ExceptionWithContext extends RuntimeException {
+    /** {@code non-null;} human-oriented context of the exception */
+    private StringBuffer context;
+
+    /**
+     * Augments the given exception with the given context, and return the
+     * result. The result is either the given exception if it was an
+     * {@link ExceptionWithContext}, or a newly-constructed exception if it
+     * was not.
+     *
+     * @param ex {@code non-null;} the exception to augment
+     * @param str {@code non-null;} context to add
+     * @return {@code non-null;} an appropriate instance
+     */
+    public static ExceptionWithContext withContext(Throwable ex, String str) {
+        ExceptionWithContext ewc;
+
+        if (ex instanceof ExceptionWithContext) {
+            ewc = (ExceptionWithContext) ex;
+        } else {
+            ewc = new ExceptionWithContext(ex);
+        }
+
+        ewc.addContext(str);
+        return ewc;
+    }
+
+    /**
+     * Constructs an instance.
+     *
+     * @param message human-oriented message
+     */
+    public ExceptionWithContext(String message) {
+        this(message, null);
+    }
+
+    /**
+     * Constructs an instance.
+     *
+     * @param cause {@code null-ok;} exception that caused this one
+     */
+    public ExceptionWithContext(Throwable cause) {
+        this(null, cause);
+    }
+
+    /**
+     * Constructs an instance.
+     *
+     * @param message human-oriented message
+     * @param cause {@code null-ok;} exception that caused this one
+     */
+    public ExceptionWithContext(String message, Throwable cause) {
+        super((message != null) ? message :
+              (cause != null) ? cause.getMessage() : null,
+              cause);
+
+        if (cause instanceof ExceptionWithContext) {
+            String ctx = ((ExceptionWithContext) cause).context.toString();
+            context = new StringBuffer(ctx.length() + 200);
+            context.append(ctx);
+        } else {
+            context = new StringBuffer(200);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void printStackTrace(PrintStream out) {
+        super.printStackTrace(out);
+        out.println(context);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void printStackTrace(PrintWriter out) {
+        super.printStackTrace(out);
+        out.println(context);
+    }
+
+    /**
+     * Adds a line of context to this instance.
+     *
+     * @param str {@code non-null;} new context
+     */
+    public void addContext(String str) {
+        if (str == null) {
+            throw new NullPointerException("str == null");
+        }
+
+        context.append(str);
+        if (!str.endsWith("\n")) {
+            context.append('\n');
+        }
+    }
+
+    /**
+     * Gets the context.
+     *
+     * @return {@code non-null;} the context
+     */
+    public String getContext() {
+        return context.toString();
+    }
+
+    /**
+     * Prints the message and context.
+     *
+     * @param out {@code non-null;} where to print to
+     */
+    public void printContext(PrintStream out) {
+        out.println(getMessage());
+        out.print(context);
+    }
+
+    /**
+     * Prints the message and context.
+     *
+     * @param out {@code non-null;} where to print to
+     */
+    public void printContext(PrintWriter out) {
+        out.println(getMessage());
+        out.print(context);
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/util/FileUtils.java b/dex/src/main/java/com/android/dex/util/FileUtils.java
new file mode 100644
index 0000000..4cea95c
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/util/FileUtils.java
@@ -0,0 +1,97 @@
+/*
+ * 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 com.android.dex.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * File I/O utilities.
+ */
+public final class FileUtils {
+    private FileUtils() {
+    }
+
+    /**
+     * Reads the named file, translating {@link IOException} to a
+     * {@link RuntimeException} of some sort.
+     *
+     * @param fileName {@code non-null;} name of the file to read
+     * @return {@code non-null;} contents of the file
+     */
+    public static byte[] readFile(String fileName) {
+        File file = new File(fileName);
+        return readFile(file);
+    }
+
+    /**
+     * Reads the given file, translating {@link IOException} to a
+     * {@link RuntimeException} of some sort.
+     *
+     * @param file {@code non-null;} the file to read
+     * @return {@code non-null;} contents of the file
+     */
+    public static byte[] readFile(File file) {
+        if (!file.exists()) {
+            throw new RuntimeException(file + ": file not found");
+        }
+
+        if (!file.isFile()) {
+            throw new RuntimeException(file + ": not a file");
+        }
+
+        if (!file.canRead()) {
+            throw new RuntimeException(file + ": file not readable");
+        }
+
+        long longLength = file.length();
+        int length = (int) longLength;
+        if (length != longLength) {
+            throw new RuntimeException(file + ": file too long");
+        }
+
+        byte[] result = new byte[length];
+
+        try {
+            FileInputStream in = new FileInputStream(file);
+            int at = 0;
+            while (length > 0) {
+                int amt = in.read(result, at, length);
+                if (amt == -1) {
+                    throw new RuntimeException(file + ": unexpected EOF");
+                }
+                at += amt;
+                length -= amt;
+            }
+            in.close();
+        } catch (IOException ex) {
+            throw new RuntimeException(file + ": trouble reading", ex);
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns true if {@code fileName} names a .zip, .jar, or .apk.
+     */
+    public static boolean hasArchiveSuffix(String fileName) {
+        return fileName.endsWith(".zip")
+                || fileName.endsWith(".jar")
+                || fileName.endsWith(".apk");
+    }
+}
diff --git a/dex/src/main/java/com/android/dex/util/Unsigned.java b/dex/src/main/java/com/android/dex/util/Unsigned.java
new file mode 100644
index 0000000..cb50d0a
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/util/Unsigned.java
@@ -0,0 +1,42 @@
+/*
+ * 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 com.android.dex.util;
+
+/**
+ * Unsigned arithmetic over Java's signed types.
+ */
+public final class Unsigned {
+    private Unsigned() {}
+
+    public static int compare(short ushortA, short ushortB) {
+        if (ushortA == ushortB) {
+            return 0;
+        }
+        int a = ushortA & 0xFFFF;
+        int b = ushortB & 0xFFFF;
+        return a < b ? -1 : 1;
+    }
+
+    public static int compare(int uintA, int uintB) {
+        if (uintA == uintB) {
+            return 0;
+        }
+        long a = uintA & 0xFFFFFFFFL;
+        long b = uintB & 0xFFFFFFFFL;
+        return a < b ? -1 : 1;
+    }
+}
diff --git a/dex/src/test/java/com/android/dex/EncodedValueReaderTest.java b/dex/src/test/java/com/android/dex/EncodedValueReaderTest.java
new file mode 100644
index 0000000..a4ca376
--- /dev/null
+++ b/dex/src/test/java/com/android/dex/EncodedValueReaderTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteArrayByteInput;
+import junit.framework.TestCase;
+
+public final class EncodedValueReaderTest extends TestCase {
+
+    public void testReadByte() {
+        assertEquals((byte) 0x80, readerOf(0, 0x80).readByte());
+        assertEquals((byte) 0xff, readerOf(0, 0xff).readByte());
+        assertEquals((byte) 0x00, readerOf(0, 0x00).readByte());
+        assertEquals((byte) 0x01, readerOf(0, 0x01).readByte());
+        assertEquals((byte) 0x7f, readerOf(0, 0x7f).readByte());
+    }
+
+    public void testReadShort() {
+        assertEquals((short) 0x8000, readerOf(34, 0x00, 0x80).readShort());
+        assertEquals((short)      0, readerOf( 2, 0x00).readShort());
+        assertEquals((short)   0xab, readerOf(34, 0xab, 0x00).readShort());
+        assertEquals((short) 0xabcd, readerOf(34, 0xcd, 0xab).readShort());
+        assertEquals((short) 0x7FFF, readerOf(34, 0xff, 0x7f).readShort());
+    }
+
+    public void testReadInt() {
+        assertEquals(0x80000000, readerOf(100, 0x00, 0x00, 0x00, 0x80).readInt());
+        assertEquals(      0x00, readerOf(  4, 0x00).readInt());
+        assertEquals(      0xab, readerOf( 36, 0xab, 0x00).readInt());
+        assertEquals(    0xabcd, readerOf( 68, 0xcd, 0xab, 0x00).readInt());
+        assertEquals(  0xabcdef, readerOf(100, 0xef, 0xcd, 0xab, 0x00).readInt());
+        assertEquals(0xabcdef01, readerOf(100, 0x01, 0xef, 0xcd, 0xab).readInt());
+        assertEquals(0x7fffffff, readerOf(100, 0xff, 0xff, 0xff, 127).readInt());
+    }
+
+    public void testReadLong() {
+        assertEquals(0x8000000000000000L, readerOf( -26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80).readLong());
+        assertEquals(              0x00L, readerOf(   6, 0x00).readLong());
+        assertEquals(              0xabL, readerOf(  38, 0xab, 0x00).readLong());
+        assertEquals(            0xabcdL, readerOf(  70, 0xcd, 0xab, 0x00).readLong());
+        assertEquals(          0xabcdefL, readerOf( 102, 0xef, 0xcd, 0xab, 0x00).readLong());
+        assertEquals(        0xabcdef01L, readerOf(-122, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong());
+        assertEquals(      0xabcdef0123L, readerOf( -90, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong());
+        assertEquals(    0xabcdef012345L, readerOf( -58, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong());
+        assertEquals(  0xabcdef01234567L, readerOf( -26, 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong());
+        assertEquals(0xabcdef0123456789L, readerOf( -26, 0x89, 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab).readLong());
+        assertEquals(0x7fffffffffffffffL, readerOf( -26, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f).readLong());
+    }
+
+    public void testReadFloat() {
+        assertEquals(Float.NEGATIVE_INFINITY, readerOf(48, -128, -1).readFloat());
+        assertEquals(Float.POSITIVE_INFINITY, readerOf(48, -128, 127).readFloat());
+        assertEquals(Float.NaN, readerOf(48, -64, 127).readFloat());
+        assertEquals(-0.0f, readerOf(16, -128).readFloat());
+        assertEquals(0.0f, readerOf(16, 0).readFloat());
+        assertEquals(0.5f, readerOf(16, 63).readFloat());
+        assertEquals(1f, readerOf(48, -128, 63).readFloat());
+        assertEquals(1.0E06f, readerOf(80, 36, 116, 73).readFloat());
+        assertEquals(1.0E12f, readerOf(112, -91, -44, 104, 83).readFloat());
+    }
+
+    public void testReadDouble() {
+        assertEquals(Double.NEGATIVE_INFINITY, readerOf(49, -16, -1).readDouble());
+        assertEquals(Double.POSITIVE_INFINITY, readerOf(49, -16, 127).readDouble());
+        assertEquals(Double.NaN, readerOf(49, -8, 127).readDouble());
+        assertEquals(-0.0, readerOf(17, -128).readDouble());
+        assertEquals(0.0, readerOf(17, 0).readDouble());
+        assertEquals(0.5, readerOf(49, -32, 63).readDouble());
+        assertEquals(1.0, readerOf(49, -16, 63).readDouble());
+        assertEquals(1.0E06, readerOf(113, -128, -124, 46, 65).readDouble());
+        assertEquals(1.0E12, readerOf(-111, -94, -108, 26, 109, 66).readDouble());
+        assertEquals(1.0E24, readerOf(-15, -76, -99, -39, 121, 67, 120, -22, 68).readDouble());
+    }
+
+    public void testReadChar() {
+        assertEquals('\u0000', readerOf( 3, 0x00).readChar());
+        assertEquals('\u00ab', readerOf( 3, 0xab).readChar());
+        assertEquals('\uabcd', readerOf(35, 0xcd, 0xab).readChar());
+        assertEquals('\uffff', readerOf(35, 0xff, 0xff).readChar());
+    }
+
+    public void testReadBoolean() {
+        assertEquals(true, readerOf(63).readBoolean());
+        assertEquals(false, readerOf(31).readBoolean());
+    }
+
+    public void testReadNull() {
+        readerOf(30).readNull();
+    }
+
+    public void testReadReference() {
+        assertEquals(      0xab, readerOf(0x17, 0xab).readString());
+        assertEquals(    0xabcd, readerOf(0x37, 0xcd, 0xab).readString());
+        assertEquals(  0xabcdef, readerOf(0x57, 0xef, 0xcd, 0xab).readString());
+        assertEquals(0xabcdef01, readerOf(0x77, 0x01, 0xef, 0xcd, 0xab).readString());
+    }
+
+    public void testReadWrongType() {
+        try {
+            readerOf(0x17, 0xab).readField();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    private EncodedValueReader readerOf(int... bytes) {
+        byte[] data = new byte[bytes.length];
+        for (int i = 0; i < bytes.length; i++) {
+            data[i] = (byte) bytes[i];
+        }
+        return new EncodedValueReader(new ByteArrayByteInput(data));
+    }
+}
diff --git a/expectations/brokentests.txt b/expectations/brokentests.txt
index dfc65e7..ae70c55 100644
--- a/expectations/brokentests.txt
+++ b/expectations/brokentests.txt
@@ -543,17 +543,6 @@
   substring: "GMT-07:00"
 },
 {
-  description: "These harmony tests are broken. The RI doesn't ship with es__TRADITIONAL, so
-                they have incorrect expectations.
-                http://b/2608750",
-  result: EXEC_FAILED,
-  names: [
-    "org.apache.harmony.text.tests.java.text.RuleBasedCollatorTest#testGetCollationElementIteratorCharacterIterator",
-    "org.apache.harmony.text.tests.java.text.RuleBasedCollatorTest#testGetCollationElementIteratorString"
-  ],
-  substring: "expected:<1> but was:<2>"
-},
-{
   description: "This test fails because on Android, RuleBasedCollators default to
                 CANONICAL_DECOMPOSITION, not NO_DECOMPOSITION.",
   result: EXEC_FAILED,
@@ -768,12 +757,6 @@
   substring: "junit.framework.AssertionFailedError: expected:<3> but was:<2>"
 },
 {
-  description: "this is testing exception priorities",
-  result: EXEC_FAILED,
-  name: "org.apache.harmony.nio.tests.java.nio.channels.DatagramChannelTest#testReadByteBuffer_readOnlyBuf",
-  substring: "java.lang.IllegalArgumentException: read-only buffer"
-},
-{
   description: "ICU doesn't provide localized pattern characters, and these tests assume the locale they're using has them.",
   result: EXEC_FAILED,
   name: "org.apache.harmony.text.tests.java.text.SimpleDateFormatTest#test_applyLocalizedPatternLjava_lang_String",
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 5d7f716..33f381f 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -3,6 +3,16 @@
  */
 [
 {
+  description: "can't compile a pattern with negative look-behind and quantifiers with upper bounds",
+  name: "org.apache.harmony.regex.tests.java.util.regex.PatternTest#test_bug_40103",
+  bug: 40103
+},
+{
+  description: "our regex implementation calls toString on CharSequences",
+  name: "org.apache.harmony.luni.tests.java.util.ScannerParseLargeFileBenchmarkTest#testParseLargeFile",
+  bug: 10133206
+},
+{
   description: "Package.getPackages(), ClassLoader.getPackages() both omit results",
   name: "libcore.java.lang.PackageTest#testGetPackages",
   bug: 5171136
@@ -249,11 +259,6 @@
   bug: 2702411
 },
 {
-  description: "Pre-NIO aliases not implemented",
-  name: "libcore.java.nio.charset.CharsetTest#test_preNioAliases",
-  bug: 3032697
-},
-{
   description: "HTTPS proxy broken on host",
   names: [
     "org.apache.harmony.luni.tests.internal.net.www.protocol.https.HttpsURLConnectionTest#testConsequentProxyConnection",
@@ -952,7 +957,7 @@
   name: "tests.api.javax.net.ssl.SSLEngineTest#testHandshake"
 },
 {
-  description: "org.apache.harmony.xnet.provider.jsse.SSLEngineImpl#getDelegatedTask() throws NPE instead of
+  description: "com.android.org.conscrypt.SSLEngineImpl#getDelegatedTask() throws NPE instead of
                 returning null",
   bug: 3403706,
   name: "tests.api.javax.net.ssl.SSLEngineTest#test_getDelegatedTask"
diff --git a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java
similarity index 79%
rename from luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java
index 330937f..b80f3a9 100644
--- a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java
@@ -21,18 +21,32 @@
 
 import junit.framework.TestCase;
 
+/**
+ * Test case of java.lang.annotation.AnnotationFormatError
+ */
 public class AnnotationFormatErrorTest extends TestCase {
+    /**
+     * @tests java.lang.annotation.AnnotationFormatError#AnnotationFormatError(String)
+     */
+    @SuppressWarnings("nls")
     public void test_constructorLjava_lang_String() {
         AnnotationFormatError e = new AnnotationFormatError("some message");
         assertEquals("some message", e.getMessage());
     }
 
+    /**
+     * @tests java.lang.annotation.AnnotationFormatError#AnnotationFormatError(Throwable)
+     */
     public void test_constructorLjava_lang_Throwable() {
         IllegalArgumentException iae = new IllegalArgumentException();
         AnnotationFormatError e = new AnnotationFormatError(iae);
         assertSame(iae, e.getCause());
     }
 
+    /**
+     * @tests java.lang.annotation.AnnotationFormatError#AnnotationFormatError(String,Throwable)
+     */
+    @SuppressWarnings("nls")
     public void test_constructorLjava_lang_StringLjava_lang_Throwable() {
         IllegalArgumentException iae = new IllegalArgumentException();
         AnnotationFormatError e = new AnnotationFormatError("some message", iae);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTypeMismatchExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTypeMismatchExceptionTest.java
new file mode 100644
index 0000000..37ee8c1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTypeMismatchExceptionTest.java
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.annotation.tests.java.lang.annotation;
+
+import java.lang.annotation.AnnotationTypeMismatchException;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case of java.lang.annotation.AnnotationTypeMismatchException
+ */
+public class AnnotationTypeMismatchExceptionTest extends TestCase {
+
+    /**
+     * @throws ClassNotFoundException 
+     * @throws SecurityException 
+     * @tests java.lang.annotation.AnnotationTypeMismatchException#AnnotationTypeMismatchException(Method,
+     *        String)
+     */
+    @SuppressWarnings("nls")
+    public void test_constructorLjava_lang_reflect_MethodLjava_lang_String() throws SecurityException, ClassNotFoundException {
+        Method[] methods = Class.forName("java.lang.String").getMethods();
+        Method m = methods[0];
+        AnnotationTypeMismatchException e = new AnnotationTypeMismatchException(
+                m, "some type");
+        assertNotNull("can not instantiate AnnotationTypeMismatchException", e);
+        assertSame("wrong method name", m, e.element());
+        assertEquals("wrong found type", "some type", e.foundType());
+    }
+}
diff --git a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java
similarity index 79%
rename from luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java
index 6c99f74..d81cabd 100644
--- a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java
@@ -22,13 +22,23 @@
 
 import junit.framework.TestCase;
 
+/**
+ * Test case of java.lang.annotation.ElementType
+ */
 public class ElementTypeTest extends TestCase {
 
+    /**
+     * @throws Exception
+     * @tests java.lang.annotation.ElementType#valueOf(String)
+     */
+    @SuppressWarnings("nls")
     public void test_valueOfLjava_lang_String() throws Exception {
-        assertSame(ElementType.ANNOTATION_TYPE, ElementType.valueOf("ANNOTATION_TYPE"));
+        assertSame(ElementType.ANNOTATION_TYPE, ElementType
+                .valueOf("ANNOTATION_TYPE"));
         assertSame(ElementType.CONSTRUCTOR, ElementType.valueOf("CONSTRUCTOR"));
         assertSame(ElementType.FIELD, ElementType.valueOf("FIELD"));
-        assertSame(ElementType.LOCAL_VARIABLE, ElementType.valueOf("LOCAL_VARIABLE"));
+        assertSame(ElementType.LOCAL_VARIABLE, ElementType
+                .valueOf("LOCAL_VARIABLE"));
         assertSame(ElementType.METHOD, ElementType.valueOf("METHOD"));
         assertSame(ElementType.PACKAGE, ElementType.valueOf("PACKAGE"));
         assertSame(ElementType.PARAMETER, ElementType.valueOf("PARAMETER"));
@@ -41,6 +51,11 @@
         }
     }
 
+    /**
+     * @throws Exception
+     * @tests java.lang.annotation.ElementType#values()
+     */
+    @SuppressWarnings("nls")
     public void test_values() throws Exception {
         ElementType[] values = ElementType.values();
         assertTrue(values.length > 1);
diff --git a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
similarity index 82%
rename from luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
index 8e1ca80..d44b90a 100644
--- a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
@@ -21,8 +21,13 @@
 
 import junit.framework.TestCase;
 
+/**
+ * 
+ */
 public class IncompleteAnnotationExceptionTest extends TestCase {
+
     /*
+     * Class under test for void IncompleteAnnotationException(String)
      * Regression for HARMONY-2477
      */
     public void testNullType() {
@@ -34,10 +39,18 @@
         }
     }
 
-    public void test_constructorLjava_lang_Class_Ljava_lang_String() throws Exception {
+    /**
+     * @throws Exception
+     * @tests java.lang.annotation.IncompleteAnnotationException#IncompleteAnnotationException(Class,
+     *        String)
+     */
+    @SuppressWarnings("nls")
+    public void test_constructorLjava_lang_Class_Ljava_lang_String()
+            throws Exception {
         Class clazz = String.class;
         String elementName = "some element";
-        IncompleteAnnotationException e = new IncompleteAnnotationException(clazz, elementName);
+        IncompleteAnnotationException e = new IncompleteAnnotationException(
+                clazz, elementName);
         assertNotNull("can not instantiate IncompleteAnnotationException", e);
         assertSame("wrong annotation type", clazz, e.annotationType());
         assertSame("wrong element name", elementName, e.elementName());
diff --git a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java
similarity index 71%
rename from luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java
index b1c2565..c4f7c03 100644
--- a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java
@@ -22,11 +22,22 @@
 
 import junit.framework.TestCase;
 
+/**
+ * Test case of java.lang.annotation.RetentionPolicy
+ */
 public class RetentionPolicyTest extends TestCase {
+    /**
+     * @throws Exception
+     * @tests java.lang.annotation.RetentionPolicy#valueOf(String)
+     */
+    @SuppressWarnings("nls")
     public void test_valueOfLjava_lang_String() throws Exception {
-        assertSame(RetentionPolicy.CLASS, RetentionPolicy.valueOf("CLASS"));
-        assertSame(RetentionPolicy.RUNTIME, RetentionPolicy.valueOf("RUNTIME"));
-        assertSame(RetentionPolicy.SOURCE, RetentionPolicy.valueOf("SOURCE"));
+        assertSame(RetentionPolicy.CLASS, RetentionPolicy
+                .valueOf("CLASS"));
+        assertSame(RetentionPolicy.RUNTIME, RetentionPolicy
+                .valueOf("RUNTIME"));
+        assertSame(RetentionPolicy.SOURCE, RetentionPolicy
+                .valueOf("SOURCE"));
         try {
             RetentionPolicy.valueOf("OTHER");
             fail("Should throw an IllegalArgumentException");
@@ -35,6 +46,11 @@
         }
     }
 
+    /**
+     * @throws Exception
+     * @tests java.lang.annotation.RetentionPolicy#values()
+     */
+    @SuppressWarnings("nls")
     public void test_values() throws Exception {
         RetentionPolicy[] values = RetentionPolicy.values();
         assertTrue(values.length > 1);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/io/BufferedReaderTest.java b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/io/BufferedReaderTest.java
new file mode 100644
index 0000000..f101c73
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/io/BufferedReaderTest.java
@@ -0,0 +1,592 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.luni.tests.java.io;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PipedReader;
+import java.io.Reader;
+import java.io.StringReader;
+
+import junit.framework.TestCase;
+import tests.support.Support_StringReader;
+
+public class BufferedReaderTest extends TestCase {
+
+	BufferedReader br;
+
+	String testString = "Test_All_Tests\nTest_java_io_BufferedInputStream\nTest_java_io_BufferedOutputStream\nTest_java_io_ByteArrayInputStream\nTest_java_io_ByteArrayOutputStream\nTest_java_io_DataInputStream\nTest_java_io_File\nTest_java_io_FileDescriptor\nTest_java_io_FileInputStream\nTest_java_io_FileNotFoundException\nTest_java_io_FileOutputStream\nTest_java_io_FilterInputStream\nTest_java_io_FilterOutputStream\nTest_java_io_InputStream\nTest_java_io_IOException\nTest_java_io_OutputStream\nTest_java_io_PrintStream\nTest_java_io_RandomAccessFile\nTest_java_io_SyncFailedException\nTest_java_lang_AbstractMethodError\nTest_java_lang_ArithmeticException\nTest_java_lang_ArrayIndexOutOfBoundsException\nTest_java_lang_ArrayStoreException\nTest_java_lang_Boolean\nTest_java_lang_Byte\nTest_java_lang_Character\nTest_java_lang_Class\nTest_java_lang_ClassCastException\nTest_java_lang_ClassCircularityError\nTest_java_lang_ClassFormatError\nTest_java_lang_ClassLoader\nTest_java_lang_ClassNotFoundException\nTest_java_lang_CloneNotSupportedException\nTest_java_lang_Double\nTest_java_lang_Error\nTest_java_lang_Exception\nTest_java_lang_ExceptionInInitializerError\nTest_java_lang_Float\nTest_java_lang_IllegalAccessError\nTest_java_lang_IllegalAccessException\nTest_java_lang_IllegalArgumentException\nTest_java_lang_IllegalMonitorStateException\nTest_java_lang_IllegalThreadStateException\nTest_java_lang_IncompatibleClassChangeError\nTest_java_lang_IndexOutOfBoundsException\nTest_java_lang_InstantiationError\nTest_java_lang_InstantiationException\nTest_java_lang_Integer\nTest_java_lang_InternalError\nTest_java_lang_InterruptedException\nTest_java_lang_LinkageError\nTest_java_lang_Long\nTest_java_lang_Math\nTest_java_lang_NegativeArraySizeException\nTest_java_lang_NoClassDefFoundError\nTest_java_lang_NoSuchFieldError\nTest_java_lang_NoSuchMethodError\nTest_java_lang_NullPointerException\nTest_java_lang_Number\nTest_java_lang_NumberFormatException\nTest_java_lang_Object\nTest_java_lang_OutOfMemoryError\nTest_java_lang_RuntimeException\nTest_java_lang_SecurityManager\nTest_java_lang_Short\nTest_java_lang_StackOverflowError\nTest_java_lang_String\nTest_java_lang_StringBuffer\nTest_java_lang_StringIndexOutOfBoundsException\nTest_java_lang_System\nTest_java_lang_Thread\nTest_java_lang_ThreadDeath\nTest_java_lang_ThreadGroup\nTest_java_lang_Throwable\nTest_java_lang_UnknownError\nTest_java_lang_UnsatisfiedLinkError\nTest_java_lang_VerifyError\nTest_java_lang_VirtualMachineError\nTest_java_lang_vm_Image\nTest_java_lang_vm_MemorySegment\nTest_java_lang_vm_ROMStoreException\nTest_java_lang_vm_VM\nTest_java_lang_Void\nTest_java_net_BindException\nTest_java_net_ConnectException\nTest_java_net_DatagramPacket\nTest_java_net_DatagramSocket\nTest_java_net_DatagramSocketImpl\nTest_java_net_InetAddress\nTest_java_net_NoRouteToHostException\nTest_java_net_PlainDatagramSocketImpl\nTest_java_net_PlainSocketImpl\nTest_java_net_Socket\nTest_java_net_SocketException\nTest_java_net_SocketImpl\nTest_java_net_SocketInputStream\nTest_java_net_SocketOutputStream\nTest_java_net_UnknownHostException\nTest_java_util_ArrayEnumerator\nTest_java_util_Date\nTest_java_util_EventObject\nTest_java_util_HashEnumerator\nTest_java_util_Hashtable\nTest_java_util_Properties\nTest_java_util_ResourceBundle\nTest_java_util_tm\nTest_java_util_Vector\n";
+
+        /**
+         * The spec says that BufferedReader.readLine() considers only "\r", "\n"
+         * and "\r\n" to be line separators. We must not permit additional separator
+         * characters.
+        */
+        public void test_readLine_IgnoresEbcdic85Characters() throws IOException {
+            assertLines("A\u0085B", "A\u0085B");
+        }
+
+        public void test_readLine_Separators() throws IOException {
+            assertLines("A\nB\nC", "A", "B", "C");
+            assertLines("A\rB\rC", "A", "B", "C");
+            assertLines("A\r\nB\r\nC", "A", "B", "C");
+            assertLines("A\n\rB\n\rC", "A", "", "B", "", "C");
+            assertLines("A\n\nB\n\nC", "A", "", "B", "", "C");
+            assertLines("A\r\rB\r\rC", "A", "", "B", "", "C");
+            assertLines("A\n\n", "A", "");
+            assertLines("A\n\r", "A", "");
+            assertLines("A\r\r", "A", "");
+            assertLines("A\r\n", "A");
+            assertLines("A\r\n\r\n", "A", "");
+        }
+
+        private void assertLines(String in, String... lines) throws IOException {
+            BufferedReader bufferedReader
+                = new BufferedReader(new Support_StringReader(in));
+            for (String line : lines) {
+                assertEquals(line, bufferedReader.readLine());
+            }
+            assertNull(bufferedReader.readLine());
+        }
+
+	/**
+	 * @tests java.io.BufferedReader#BufferedReader(java.io.Reader)
+	 */
+	public void test_ConstructorLjava_io_Reader() {
+		// Test for method java.io.BufferedReader(java.io.Reader)
+		assertTrue("Used in tests", true);
+	}
+
+	/**
+	 * @tests java.io.BufferedReader#BufferedReader(java.io.Reader, int)
+	 */
+	public void test_ConstructorLjava_io_ReaderI() {
+		// Test for method java.io.BufferedReader(java.io.Reader, int)
+		assertTrue("Used in tests", true);
+	}
+
+	/**
+	 * @tests java.io.BufferedReader#close()
+	 */
+	public void test_close() {
+		// Test for method void java.io.BufferedReader.close()
+		try {
+			br = new BufferedReader(new Support_StringReader(testString));
+			br.close();
+			br.read();
+			fail("Read on closed stream");
+		} catch (IOException x) {
+			return;
+		}
+	}
+
+	/**
+	 * @tests java.io.BufferedReader#mark(int)
+	 */
+	public void test_markI() throws IOException {
+		// Test for method void java.io.BufferedReader.mark(int)
+		char[] buf = null;
+		br = new BufferedReader(new Support_StringReader(testString));
+		br.skip(500);
+		br.mark(1000);
+		br.skip(250);
+		br.reset();
+		buf = new char[testString.length()];
+		br.read(buf, 0, 500);
+		assertTrue("Failed to set mark properly", testString.substring(500,
+				1000).equals(new String(buf, 0, 500)));
+
+		try {
+			br = new BufferedReader(new Support_StringReader(testString), 800);
+			br.skip(500);
+			br.mark(250);
+			br.read(buf, 0, 1000);
+			br.reset();
+			fail("Failed to invalidate mark properly");
+		} catch (IOException x) {
+		    // Expected
+		}
+
+		char[] chars = new char[256];
+		for (int i = 0; i < 256; i++)
+			chars[i] = (char) i;
+		Reader in = new BufferedReader(new Support_StringReader(new String(
+				chars)), 12);
+
+		in.skip(6);
+		in.mark(14);
+		in.read(new char[14], 0, 14);
+		in.reset();
+		assertTrue("Wrong chars", in.read() == (char) 6
+				&& in.read() == (char) 7);
+
+		in = new BufferedReader(new Support_StringReader(new String(chars)), 12);
+		in.skip(6);
+		in.mark(8);
+		in.skip(7);
+		in.reset();
+		assertTrue("Wrong chars 2", in.read() == (char) 6
+				&& in.read() == (char) 7);
+		
+        BufferedReader br = new BufferedReader(new StringReader("01234"), 2);
+        br.mark(3);
+        char[] carray = new char[3];
+        int result = br.read(carray);
+        assertEquals(3, result);
+        assertEquals("Assert 0:", '0', carray[0]);
+        assertEquals("Assert 1:", '1', carray[1]);
+        assertEquals("Assert 2:", '2', carray[2]);
+        assertEquals("Assert 3:", '3', br.read());
+
+        br = new BufferedReader(new StringReader("01234"), 2);
+        br.mark(3);
+        carray = new char[4];
+        result = br.read(carray);
+        assertEquals("Assert 4:", 4, result);
+        assertEquals("Assert 5:", '0', carray[0]);
+        assertEquals("Assert 6:", '1', carray[1]);
+        assertEquals("Assert 7:", '2', carray[2]);
+        assertEquals("Assert 8:", '3', carray[3]);
+        assertEquals("Assert 9:", '4', br.read());
+        assertEquals("Assert 10:", -1, br.read());
+
+        BufferedReader reader = new BufferedReader(new StringReader("01234"));
+        reader.mark(Integer.MAX_VALUE);
+        reader.read();
+        reader.close();
+	}
+
+	/**
+	 * @tests java.io.BufferedReader#markSupported()
+	 */
+	public void test_markSupported() {
+		// Test for method boolean java.io.BufferedReader.markSupported()
+		br = new BufferedReader(new Support_StringReader(testString));
+		assertTrue("markSupported returned false", br.markSupported());
+	}
+
+	/**
+	 * @tests java.io.BufferedReader#read()
+	 */
+	public void test_read() throws IOException {
+		// Test for method int java.io.BufferedReader.read()
+		try {
+			br = new BufferedReader(new Support_StringReader(testString));
+			int r = br.read();
+			assertTrue("Char read improperly", testString.charAt(0) == r);
+			br = new BufferedReader(new Support_StringReader(new String(
+					new char[] { '\u8765' })));
+			assertTrue("Wrong double byte character", br.read() == '\u8765');
+		} catch (java.io.IOException e) {
+			fail("Exception during read test");
+		}
+
+		char[] chars = new char[256];
+		for (int i = 0; i < 256; i++)
+			chars[i] = (char) i;
+		Reader in = new BufferedReader(new Support_StringReader(new String(
+				chars)), 12);
+		try {
+			assertEquals("Wrong initial char", 0, in.read()); // Fill the
+			// buffer
+			char[] buf = new char[14];
+			in.read(buf, 0, 14); // Read greater than the buffer
+			assertTrue("Wrong block read data", new String(buf)
+					.equals(new String(chars, 1, 14)));
+			assertEquals("Wrong chars", 15, in.read()); // Check next byte
+		} catch (IOException e) {
+			fail("Exception during read test 2:" + e);
+		}
+		
+		// regression test for HARMONY-841
+		assertTrue(new BufferedReader(new CharArrayReader(new char[5], 1, 0), 2).read() == -1);
+	}
+
+	/**
+	 * @tests java.io.BufferedReader#read(char[], int, int)
+	 */
+	public void test_read$CII() throws Exception{
+		char[] ca = new char[2];
+		BufferedReader toRet = new BufferedReader(new InputStreamReader(
+				new ByteArrayInputStream(new byte[0])));
+		
+		/* Null buffer should throw NPE even when len == 0 */
+		try {
+			toRet.read(null, 1, 0);
+			fail("null buffer reading zero bytes should throw NPE");
+		} catch (NullPointerException e) {
+			//expected
+		}
+		
+		try {
+			toRet.close();
+		} catch (IOException e) {
+			fail("unexpected 1: " + e);
+		}
+		
+		try {
+			toRet.read(null, 1, 0);
+			fail("null buffer reading zero bytes on closed stream should throw IOException");
+		} catch (IOException e) {
+			//expected
+		}
+
+		/* Closed reader should throw IOException reading zero bytes */
+		try {
+			toRet.read(ca, 0, 0);
+			fail("Reading zero bytes on a closed reader should not work");
+		} catch (IOException e) {
+			// expected
+		}
+
+		/*
+		 * Closed reader should throw IOException in preference to index out of
+		 * bounds
+		 */
+		try {
+			// Read should throw IOException before
+			// ArrayIndexOutOfBoundException
+			toRet.read(ca, 1, 5);
+			fail("IOException should have been thrown");
+		} catch (IOException e) {
+			// expected
+		}
+
+		// Test to ensure that a drained stream returns 0 at EOF
+		toRet = new BufferedReader(new InputStreamReader(
+				new ByteArrayInputStream(new byte[2])));
+		try {
+			assertEquals("Emptying the reader should return two bytes", 2,
+					toRet.read(ca, 0, 2));
+			assertEquals("EOF on a reader should be -1", -1, toRet.read(ca, 0,
+					2));
+			assertEquals("Reading zero bytes at EOF should work", 0, toRet
+					.read(ca, 0, 0));
+		} catch (IOException ex) {
+			fail("Unexpected IOException : " + ex.getLocalizedMessage());
+		}
+
+		// Test for method int java.io.BufferedReader.read(char [], int, int)
+		try {
+			char[] buf = new char[testString.length()];
+			br = new BufferedReader(new Support_StringReader(testString));
+			br.read(buf, 50, 500);
+			assertTrue("Chars read improperly", new String(buf, 50, 500)
+					.equals(testString.substring(0, 500)));
+		} catch (java.io.IOException e) {
+			fail("Exception during read test");
+		}
+
+		BufferedReader bufin = new BufferedReader(new Reader() {
+			int size = 2, pos = 0;
+
+			char[] contents = new char[size];
+
+			public int read() throws IOException {
+				if (pos >= size)
+					throw new IOException("Read past end of data");
+				return contents[pos++];
+			}
+
+			public int read(char[] buf, int off, int len) throws IOException {
+				if (pos >= size)
+					throw new IOException("Read past end of data");
+				int toRead = len;
+				if (toRead > (size - pos))
+					toRead = size - pos;
+				System.arraycopy(contents, pos, buf, off, toRead);
+				pos += toRead;
+				return toRead;
+			}
+
+			public boolean ready() throws IOException {
+				return size - pos > 0;
+			}
+
+			public void close() throws IOException {
+			}
+		});
+		try {
+			bufin.read();
+			int result = bufin.read(new char[2], 0, 2);
+			assertTrue("Incorrect result: " + result, result == 1);
+		} catch (IOException e) {
+			fail("Unexpected: " + e);
+		}
+        
+        //regression for HARMONY-831
+        try{
+            new BufferedReader(new PipedReader(), 9).read(new char[] {}, 7, 0);
+            fail("should throw IndexOutOfBoundsException");
+        }catch(IndexOutOfBoundsException e){
+        }
+        
+        // Regression for HARMONY-54
+        char[] ch = {};
+        BufferedReader reader = new BufferedReader(new CharArrayReader(ch));
+        try {
+            // Check exception thrown when the reader is open.
+            reader.read(null, 1, 0);
+            fail("Assert 0: NullPointerException expected");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+
+        // Now check IOException is thrown in preference to
+        // NullPointerexception when the reader is closed.
+        reader.close();
+        try {
+            reader.read(null, 1, 0);
+            fail("Assert 1: IOException expected");
+        } catch (IOException e) {
+            // Expected
+        }
+
+        try {
+            // And check that the IOException is thrown before
+            // ArrayIndexOutOfBoundException
+            reader.read(ch, 0, 42);
+            fail("Assert 2: IOException expected");
+        } catch (IOException e) {
+            // expected
+        }
+	}
+
+	/**
+	 * @tests java.io.BufferedReader#read(char[], int, int)
+	 */
+	public void test_read_$CII_Exception() throws IOException {
+		br = new BufferedReader(new Support_StringReader(testString));
+		char[] nullCharArray = null;
+		char[] charArray = testString.toCharArray();
+		
+		try {
+			br.read(nullCharArray, -1, -1);
+			fail();
+		} catch (NullPointerException expected) {
+		} catch (IndexOutOfBoundsException expected) {
+		}
+		
+		try {
+			br.read(nullCharArray, -1, 0);
+			fail();
+		} catch (NullPointerException expected) {
+		} catch (IndexOutOfBoundsException expected) {
+		}
+
+		try {
+			br.read(nullCharArray, 0, -1);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+
+		try {
+			br.read(nullCharArray, 0, 0);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+		
+		try {
+			br.read(nullCharArray, 0, 1);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+		
+		try {
+			br.read(charArray, -1, -1);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+
+		try {
+			br.read(charArray, -1, 0);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+
+		br.read(charArray, 0, 0);
+        br.read(charArray, 0, charArray.length);
+        br.read(charArray, charArray.length, 0);
+		
+		try {
+			br.read(charArray, charArray.length + 1, 0);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			//expected
+		}
+		
+		try {
+			br.read(charArray, charArray.length + 1, 1);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			//expected
+		}
+
+		br.close();
+
+		try {
+			br.read(nullCharArray, -1, -1);
+			fail("should throw IOException");
+		} catch (IOException e) {
+			// expected
+		}
+
+		try {
+			br.read(charArray, -1, 0);
+			fail("should throw IOException");
+		} catch (IOException e) {
+			// expected
+		}
+
+		try {
+			br.read(charArray, 0, -1);
+			fail("should throw IOException");
+		} catch (IOException e) {
+			// expected
+		}
+	}
+	/**
+	 * @tests java.io.BufferedReader#readLine()
+	 */
+	public void test_readLine() {
+		// Test for method java.lang.String java.io.BufferedReader.readLine()
+		try {
+			br = new BufferedReader(new Support_StringReader(testString));
+			String r = br.readLine();
+			assertEquals("readLine returned incorrect string", "Test_All_Tests", r
+					);
+		} catch (java.io.IOException e) {
+			fail("Exception during readLine test");
+		}
+	}
+
+	/**
+	 * @tests java.io.BufferedReader#ready()
+	 */
+	public void test_ready() {
+		// Test for method boolean java.io.BufferedReader.ready()
+		try {
+			br = new BufferedReader(new Support_StringReader(testString));
+			assertTrue("ready returned false", br.ready());
+		} catch (java.io.IOException e) {
+			fail("Exception during ready test" + e.toString());
+		}
+	}
+
+	/**
+	 * @tests java.io.BufferedReader#reset()
+	 */
+	public void test_reset() {
+		// Test for method void java.io.BufferedReader.reset()
+		try {
+			br = new BufferedReader(new Support_StringReader(testString));
+			br.skip(500);
+			br.mark(900);
+			br.skip(500);
+			br.reset();
+			char[] buf = new char[testString.length()];
+			br.read(buf, 0, 500);
+			assertTrue("Failed to reset properly", testString.substring(500,
+					1000).equals(new String(buf, 0, 500)));
+		} catch (java.io.IOException e) {
+			fail("Exception during reset test");
+		}
+		try {
+			br = new BufferedReader(new Support_StringReader(testString));
+			br.skip(500);
+			br.reset();
+			fail("Reset succeeded on unmarked stream");
+		} catch (IOException x) {
+			return;
+
+		}
+	}
+
+    public void test_reset_IOException() throws Exception {
+        int[] expected = new int[] { '1', '2', '3', '4', '5', '6', '7', '8',
+                '9', '0', -1 };
+        br = new BufferedReader(new Support_StringReader("1234567890"), 9);
+        br.mark(9);
+        for (int i = 0; i < 11; i++) {
+            assertEquals(expected[i], br.read());
+        }
+        try {
+            br.reset();
+            fail("should throw IOException");
+        } catch (IOException e) {
+            // Expected
+        }
+        for (int i = 0; i < 11; i++) {
+            assertEquals(-1, br.read());
+        }
+
+        br = new BufferedReader(new Support_StringReader("1234567890"));
+        br.mark(10);
+        for (int i = 0; i < 10; i++) {
+            assertEquals(expected[i], br.read());
+        }
+        br.reset();
+        for (int i = 0; i < 11; i++) {
+            assertEquals(expected[i], br.read());
+        }
+    }
+
+	/**
+	 * @tests java.io.BufferedReader#skip(long)
+	 */
+	public void test_skipJ() {
+		// Test for method long java.io.BufferedReader.skip(long)
+		try {
+			br = new BufferedReader(new Support_StringReader(testString));
+			br.skip(500);
+			char[] buf = new char[testString.length()];
+			br.read(buf, 0, 500);
+			assertTrue("Failed to set skip properly", testString.substring(500,
+					1000).equals(new String(buf, 0, 500)));
+		} catch (java.io.IOException e) {
+			fail("Exception during skip test");
+		}
+
+	}
+
+	/**
+	 * Sets up the fixture, for example, open a network connection. This method
+	 * is called before a test is executed.
+	 */
+	protected void setUp() {
+	}
+
+	/**
+	 * Tears down the fixture, for example, close a network connection. This
+	 * method is called after a test is executed.
+	 */
+	protected void tearDown() {
+		try {
+			br.close();
+		} catch (Exception e) {
+		}
+	}
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerParseLargeFileBenchmarkTest.java b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerParseLargeFileBenchmarkTest.java
new file mode 100644
index 0000000..117f211
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerParseLargeFileBenchmarkTest.java
@@ -0,0 +1,76 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.luni.tests.java.util;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Scanner;
+
+import junit.framework.TestCase;
+
+public class ScannerParseLargeFileBenchmarkTest extends TestCase {
+
+    /**
+     * This test will check when parse a large file like more than 200M bytes if
+     * the Scanner will exhaust all heap memory
+     */
+    public void testParseLargeFile() throws Exception {
+        MyReader reader = new MyReader();
+        String delimiter = "\r?\n";
+        Scanner scanner = new Scanner(reader).useDelimiter(delimiter);
+
+        while (scanner.hasNext()) {
+            scanner.next();
+        }
+        scanner.close();
+        reader.close();
+    }
+
+    private static class MyReader extends Reader {
+        static final char[] CONTENT = "large file!\n".toCharArray();
+
+        static long fileLength = (8 << 21) * 12;
+
+        static boolean first = true;
+
+        static int position = 0;
+
+        private int count = 0;
+
+        @Override
+        public void close() throws IOException {
+        }
+
+        @Override
+        public int read(char[] buf, int offset, int length) {
+            if (count >= fileLength) {
+                return -1;
+            }
+            if (first == true) {
+                position = 0;
+                first = false;
+            }
+            for (int i = offset; i < length; i++) {
+                buf[i] = CONTENT[(i + position) % CONTENT.length];
+                count++;
+            }
+
+            position = (length + position) % CONTENT.length;
+
+            return length - offset;
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerTest.java b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerTest.java
new file mode 100644
index 0000000..459bce1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerTest.java
@@ -0,0 +1,5741 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.luni.tests.java.util;
+
+import java.io.Closeable;
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.CharBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.InputMismatchException;
+import java.util.List;
+import java.util.Locale;
+import java.util.NoSuchElementException;
+import java.util.Scanner;
+import java.util.regex.MatchResult;
+import java.util.regex.Pattern;
+
+import junit.framework.TestCase;
+
+public class ScannerTest extends TestCase {
+
+    private Scanner s;
+
+    private ServerSocket server;
+
+    private SocketAddress address;
+
+    private SocketChannel client;
+
+    private Socket serverSocket;
+
+    private OutputStream os;
+
+    private static class MockCloseable implements Closeable, Readable {
+
+        public void close() throws IOException {
+            throw new IOException();
+        }
+
+        public int read(CharBuffer cb) throws IOException {
+            throw new EOFException();
+        }
+
+    }
+
+    /**
+     * @tests java.util.Scanner#Scanner(File)
+     */
+    public void test_ConstructorLjava_io_File() throws IOException {
+        File tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+        s = new Scanner(tmpFile);
+        assertNotNull(s);
+        s.close();
+        assertTrue(tmpFile.delete());
+
+        try {
+            s = new Scanner(tmpFile);
+            fail("should throw FileNotFoundException");
+        } catch (FileNotFoundException e) {
+            // expected
+        }
+
+        tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+        FileOutputStream fos = new FileOutputStream(tmpFile);
+        fos.write("test".getBytes());
+
+        s = new Scanner(tmpFile);
+        tmpFile.delete();
+
+        // Scanner(File = null)
+        try {
+            s = new Scanner((File) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // TODO: test if the default charset is used.
+    }
+
+    /**
+     * @tests java.util.Scanner#Scanner(File, String)
+     */
+    public void test_ConstructorLjava_io_FileLjava_lang_String()
+            throws IOException {
+        File tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+        s = new Scanner(tmpFile, Charset.defaultCharset().name());
+        assertNotNull(s);
+        s.close();
+        assertTrue(tmpFile.delete());
+
+        try {
+            s = new Scanner(tmpFile, Charset.defaultCharset().name());
+            fail("should throw FileNotFoundException");
+        } catch (FileNotFoundException e) {
+            // expected
+        }
+
+        try {
+            s = new Scanner(tmpFile, null);
+            fail("should throw FileNotFoundException");
+        } catch (FileNotFoundException e) {
+            // expected
+        }
+
+        tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+        try {
+            s = new Scanner(tmpFile, "invalid charset");
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        //fail on RI. File is opened but not closed when exception is thrown on
+        // RI.
+        assertTrue(tmpFile.delete());
+
+        // Scanner(File = null, Charset = null)
+        try {
+            s = new Scanner((File) null, null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // Scanner(File = null, Charset = UTF-8)
+        try {
+            s = new Scanner((File) null, "UTF-8");
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // Scanner(File = null, Charset = invalid)
+        try {
+            s = new Scanner((File) null, "invalid");
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // Scanner(File, Charset = null)
+        try {
+            File f = File.createTempFile("test", ".tmp");
+            s = new Scanner(f, null);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        // TODO: test if the specified charset is used.
+    }
+
+    /**
+     * @tests java.util.Scanner#Scanner(InputStream)
+     */
+    public void test_ConstructorLjava_io_InputStream() {
+        s = new Scanner(new PipedInputStream());
+        assertNotNull(s);
+        s.close();
+
+        // Scanner(InputStream)
+        try {
+            s = new Scanner((InputStream) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // TODO: test if the default charset is used.
+    }
+
+    /**
+     * @tests java.util.Scanner#Scanner(InputStream, String)
+     */
+    public void test_ConstructorLjava_io_InputStreamLjava_lang_String() {
+        s = new Scanner(new PipedInputStream(), Charset.defaultCharset().name());
+        assertNotNull(s);
+        s.close();
+
+        try {
+            s = new Scanner((PipedInputStream) null, "invalid charset");
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            s = new Scanner(new PipedInputStream(), null);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            s = new Scanner(new PipedInputStream(), "invalid charset");
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        // TODO: test if the specified charset is used.
+    }
+
+    /**
+     * @tests java.util.Scanner#Scanner(Readable)
+     */
+    public void test_ConstructorLjava_lang_Readable() {
+        s = new Scanner(new StringReader("test string"));
+        assertNotNull(s);
+        s.close();
+
+        // Scanner(Readable)
+        try {
+            s = new Scanner((Readable) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.util.Scanner#Scanner(ReadableByteChannel)
+     */
+    public void test_ConstructorLjava_nio_channels_ReadableByteChannel()
+            throws IOException {
+        File tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+        FileChannel fc = new FileOutputStream(tmpFile).getChannel();
+        s = new Scanner(fc);
+        assertNotNull(s);
+        s.close();
+        assertTrue(tmpFile.delete());
+
+        // Scanner(ReadableByteChannel)
+        try {
+            s = new Scanner((ReadableByteChannel) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // Test if the default charset is used.
+        String sampleData = "1 2 3 4 5 6 7 8 9 10";
+        File tempFile = File.createTempFile("harmony", "test");
+        tempFile.deleteOnExit();
+        FileOutputStream os = new FileOutputStream(tempFile);
+        os.write(sampleData.getBytes());
+        os.close();
+
+        FileInputStream is = new FileInputStream(tempFile);
+        FileChannel channel = is.getChannel();
+
+        Scanner s = new Scanner(channel);
+        int count = 0;
+        while (s.hasNextInt()) {
+            s.nextInt();
+            count++;
+        }
+        channel.close();
+        assertEquals(10, count);
+    }
+
+    /**
+     * @tests java.util.Scanner#Scanner(ReadableByteChannel, String)
+     */
+    public void test_ConstructorLjava_nio_channels_ReadableByteChannelLjava_lang_String()
+            throws IOException {
+        File tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+        FileChannel fc = new FileOutputStream(tmpFile).getChannel();
+        s = new Scanner(fc, Charset.defaultCharset().name());
+        assertNotNull(s);
+        s.close();
+
+        fc = new FileOutputStream(tmpFile).getChannel();
+        try {
+            s = new Scanner(fc, "invalid charset");
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        fc.close();
+        assertTrue(tmpFile.delete());
+
+        // Scanner(ReadableByteChannel = null, Charset = null)
+        try {
+            s = new Scanner((ReadableByteChannel) null, null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // Scanner(ReadableByteChannel = null, Charset = invalid)
+        try {
+            s = new Scanner((ReadableByteChannel) null, "invalid");
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // Scanner(ReadableByteChannel, Charset = null)
+        try {
+            s = new Scanner(fc, null);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        // TODO: test if the specified charset is used.
+    }
+
+    /**
+     * @tests java.util.Scanner#Scanner(String)
+     */
+    public void test_ConstructorLjava_lang_String() {
+        s = new Scanner("test string");
+        assertNotNull(s);
+        s.close();
+
+        // Scanner(String)
+        try {
+            s = new Scanner((String) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.util.Scanner#close()
+     */
+    public void test_close() throws IOException {
+        File tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+        FileOutputStream fos = new FileOutputStream(tmpFile);
+        FileChannel fc = fos.getChannel();
+        s = new Scanner(fc);
+
+        // Write out a int before the scanner is closed, should be OK.
+        fos.write(12);
+
+        s.close();
+        assertFalse(fc.isOpen());
+
+        // Write out a int after the scanner is closed, IOException should be
+        // thrown out.
+        try {
+            fos.write(12);
+            fail("Should throw IOException");
+        } catch (IOException e) {
+            // expected
+        }
+
+        s.close(); // no exception should be thrown
+        assertTrue(tmpFile.delete());
+    }
+
+    /**
+     * @tests java.util.Scanner#ioException()
+     */
+    public void test_ioException() throws IOException {
+        MockCloseable mc = new MockCloseable();
+        s = new Scanner(mc);
+        assertNull(s.ioException()); // No operation, no exception
+
+        s.close(); // IOException should be cached
+        assertNotNull(s.ioException());
+        assertTrue(s.ioException() instanceof IOException);
+    }
+
+    /**
+     * @tests java.util.Scanner#delimiter()
+     */
+    public void test_delimiter() {
+        s = new Scanner("test");
+        Pattern pattern = s.delimiter();
+        assertEquals("\\p{javaWhitespace}+", pattern.toString());
+    }
+
+    /**
+     * @tests java.util.Scanner#useDelimiter(Pattern)
+     */
+    public void test_useDelimiter_LPattern() {
+        s = new Scanner("test");
+        s.useDelimiter(Pattern.compile("\\w+"));
+        assertEquals("\\w+", s.delimiter().toString());
+
+        s = new Scanner("test");
+        s.useDelimiter((Pattern) null);
+        assertNull(s.delimiter());
+    }
+
+    /**
+     * @tests java.util.Scanner#useDelimiter(String)
+     */
+    public void test_useDelimiter_String() {
+        s = new Scanner("test");
+        try {
+            s.useDelimiter((String) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        s = new Scanner("test");
+        s.useDelimiter("\\w+");
+        assertEquals("\\w+", s.delimiter().toString());
+    }
+
+    /**
+     * @tests java.util.Scanner#locale()
+     */
+    public void test_locale() {
+        s = new Scanner("test");
+        assertEquals(Locale.getDefault(), s.locale());
+    }
+
+    /**
+     * @tests java.util.Scanner#useLocale(Locale)
+     */
+    public void test_useLocale_LLocale() {
+        s = new Scanner("test");
+        try {
+            s.useLocale(null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        s.useLocale(new Locale("test", "test"));
+        assertEquals(new Locale("test", "test"), s.locale());
+    }
+
+    /**
+     * @tests java.util.Scanner#radix()
+     */
+    public void test_radix() {
+        s = new Scanner("test");
+        assertEquals(10, s.radix());
+    }
+
+    /**
+     * @tests java.util.Scanner#useRadix()
+     */
+    public void test_useRadix_I() {
+        s = new Scanner("test");
+        try {
+            s.useRadix(Character.MIN_RADIX - 1);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            s.useRadix(Character.MAX_RADIX + 1);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        s.useRadix(11);
+        assertEquals(11, s.radix());
+    }
+
+    /**
+     * @tests java.util.Scanner#remove()
+     */
+    public void test_remove() {
+        s = new Scanner("aab*b*").useDelimiter("\\*");
+        try {
+            s.remove();
+            fail("should throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+            //Expected
+        }
+    }
+
+    /**
+     * @tests java.util.Scanner#match()
+     */
+    public void test_match() {
+        MatchResult result ;
+        s = new Scanner("1 2 ");
+        try {
+            s.match();
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // Expected
+        }
+        assertEquals("1", s.next());
+        assertEquals("2", s.next());
+        result = s.match();
+        assertEquals(2, result.start());
+        assertEquals(3, result.end());
+        assertEquals(2, result.start(0));
+        assertEquals(3, result.end(0));
+        assertEquals("2", result.group());
+        assertEquals("2", result.group(0));
+        assertEquals(0, result.groupCount());
+        try {
+            result.start(1);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // Expected
+        }
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+        try {
+            s.match();
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // Expected
+        }
+        
+        s = new Scanner("True faLse");
+        try {
+            s.match();
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // Expected
+        }
+        assertTrue(s.nextBoolean());
+        result = s.match();
+        assertEquals(0, result.start());
+        assertEquals(4, result.end());
+        assertEquals(0, result.start(0));
+        assertEquals(4, result.end(0));
+        assertEquals("True", result.group());
+        assertEquals(0, result.groupCount());
+        assertFalse(s.nextBoolean());
+        try {
+            s.nextBoolean();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+        try {
+            s.match();
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // Expected
+        }
+        
+        s = new Scanner("True faLse");
+        assertTrue(s.nextBoolean());
+        result = s.match();
+        assertEquals(0, result.start());
+        assertEquals(4, result.end());
+        assertEquals(0, result.start(0));
+        assertEquals(4, result.end(0));
+        assertEquals("True", result.group());
+        assertEquals(0, result.groupCount());
+        s.close();
+        try {
+            s.nextBoolean();
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // Expected
+        }
+        result = s.match();
+        assertEquals(0, result.start());
+        assertEquals(4, result.end());
+        assertEquals(0, result.start(0));
+        assertEquals(4, result.end(0));
+        assertEquals("True", result.group());
+        assertEquals(0, result.groupCount());
+        
+        s = new Scanner("True fase");
+        assertTrue(s.nextBoolean());
+        assertEquals(0, result.groupCount());
+        try {
+            s.nextBoolean();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        try {
+            s.match();
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // Expected
+        }
+        
+        s = new Scanner("True fase");
+        assertTrue(s.nextBoolean());
+        try {
+            s.next((Pattern)null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+        result = s.match();
+        assertEquals(0, result.start());
+        assertEquals(4, result.end());
+        assertEquals(0, result.start(0));
+        assertEquals(4, result.end(0));
+        assertEquals("True", result.group());
+        assertEquals(0, result.groupCount());
+        
+    }
+     
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#next()
+     */
+    public void test_next() throws IOException {
+        // use special delimiter
+        s = new Scanner("1**2").useDelimiter("\\*");
+        assertEquals("1", s.next());
+        assertEquals("", s.next());
+        assertEquals("2", s.next());
+
+        s = new Scanner(" \t 1 \t 2").useDelimiter("\\s*");
+        assertEquals("1", s.next());
+        assertEquals("2", s.next());
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+        
+        s = new Scanner("a").useDelimiter("a?");
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+        
+        s = new Scanner("aa").useDelimiter("a?");
+        assertEquals("", s.next());
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+        
+
+        s = new Scanner("word( )test( )").useDelimiter("\\( \\)");
+        assertEquals("word", s.next());
+        assertEquals("test", s.next());
+
+        s = new Scanner("? next  ").useDelimiter("( )");
+        assertEquals("?", s.next());
+        assertEquals("next", s.next());
+        assertEquals("", s.next());
+
+        s = new Scanner("word1 word2  ");
+        assertEquals("word1", s.next());
+        assertEquals("word2", s.next());
+        // test boundary case
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // just delimiter exists in this scanner
+        s = new Scanner(" ");
+        try {
+            s.next();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // nothing exists in this scanner
+        s = new Scanner("");
+        try {
+            s.next();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // no delimiter exists in this scanner
+        s = new Scanner("test");
+        assertEquals("test", s.next());
+
+        // input resourse starts with delimiter
+        s = new Scanner("  test");
+        assertEquals("test", s.next());
+
+        // input resource ends with delimiter
+        s = new Scanner("  test  ");
+        assertEquals("test", s.next());
+
+        // Harmony uses 1024 as default buffer size,
+        // What if a sentence can not be read in all in once.
+        StringBuilder longSentence = new StringBuilder(1025);
+        for (int i = 0; i < 11; i++) {
+            longSentence.append(" ");
+        }
+        for (int i = 11; i < 1026; i++) {
+            longSentence.append("a");
+        }
+        s = new Scanner(longSentence.toString());
+        assertEquals(longSentence.toString().trim(), s.next());
+
+        s = new Scanner(" test test");
+        assertEquals("test", s.next());
+        assertEquals("test", s.next());
+
+        // What if use a delimiter of length 0.
+        s = new Scanner("test\ntest").useDelimiter(Pattern.compile("^",
+                Pattern.MULTILINE));
+        assertEquals("test\n", s.next());
+        assertEquals("test", s.next());
+        
+        s = new Scanner("").useDelimiter(Pattern.compile("^",
+                Pattern.MULTILINE));
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+        
+        s = new Scanner("").useDelimiter(Pattern.compile("^*",
+                Pattern.MULTILINE));
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("test\ntest").useDelimiter(Pattern.compile("^*",
+                Pattern.MULTILINE));
+        assertEquals("t", s.next());
+        assertEquals("e", s.next());
+
+        s = new Scanner("\ntest\ntest").useDelimiter(Pattern.compile("$",
+                Pattern.MULTILINE));
+        assertEquals("\ntest", s.next());
+        assertEquals("\ntest", s.next());
+
+        // test socket inputStream
+        // Harmony uses 1024 as default buffer size,
+        // what if the leading delimiter is larger than 1023
+        for (int i = 0; i < 1024; i++) {
+            os.write(" ".getBytes());
+        }
+        os.write("  1 2 ".getBytes());
+        s = new Scanner(client);
+        assertEquals("1", s.next());
+        assertEquals("2", s.next());
+        os.write("  1 2".getBytes());
+        serverSocket.close();
+        assertEquals("1", s.next());
+        assertEquals("2", s.next());
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#next(Pattern)
+     */
+    public void test_nextLPattern() throws IOException {
+        Pattern pattern;
+        s = new Scanner("aab*2*").useDelimiter("\\*");
+        pattern = Pattern.compile("a*b");
+        assertEquals("aab", s.next(pattern));
+        try {
+            s.next(pattern);
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("word ? ");
+        pattern = Pattern.compile("\\w+");
+        assertEquals("word", s.next(pattern));
+        try {
+            s.next(pattern);
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("word1 word2  ");
+        pattern = Pattern.compile("\\w+");
+        assertEquals("word1", s.next(pattern));
+        assertEquals("word2", s.next(pattern));
+        // test boundary case
+        try {
+            s.next(pattern);
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // test socket inputStream
+
+        os.write("aab 2".getBytes());
+        serverSocket.close();
+
+        s = new Scanner(client);
+        pattern = Pattern.compile("a*b");
+        assertEquals("aab", s.next(pattern));
+        try {
+            s.next(pattern);
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#next(String)
+     */
+    public void test_nextLString() throws IOException {
+        s = new Scanner("b*a*").useDelimiter("\\*");
+        assertEquals("b", s.next("a*b"));
+        try {
+            s.next("a*b");
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("word ? ");
+        assertEquals("word", s.next("\\w+"));
+        try {
+            s.next("\\w+");
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("word1 next  ");
+        assertEquals("word1", s.next("\\w+"));
+        assertEquals("next", s.next("\\w+"));
+        // test boundary case
+        try {
+            s.next("\\w+");
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // test socket inputStream
+        os.write("aab 2".getBytes());
+        serverSocket.close();
+
+        s = new Scanner(client);
+        assertEquals("aab", s.next("a*b"));
+        try {
+            s.next("a*b");
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextBoolean()
+     */
+    public void test_nextBoolean() throws IOException {
+        // case insensitive
+        s = new Scanner("TRue");
+        assertTrue(s.nextBoolean());
+
+        s = new Scanner("tRue false");
+        assertTrue(s.nextBoolean());
+        assertFalse(s.nextBoolean());
+        try {
+            s.nextBoolean();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("true1");
+        try {
+            s.nextBoolean();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        try {
+            s = new Scanner("");
+            s.nextBoolean();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // test socket inputStream
+        os.write("true false".getBytes());
+        serverSocket.close();
+
+        s = new Scanner(client);
+        assertTrue(s.nextBoolean());
+        assertFalse(s.nextBoolean());
+
+        // ues '*' as delimiter
+        s = new Scanner("true**false").useDelimiter("\\*");
+        assertTrue(s.nextBoolean());
+        try {
+            s.nextBoolean();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("false( )").useDelimiter("\\( \\)");
+        assertFalse(s.nextBoolean());
+
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextInt(int)
+     */
+    public void test_nextIntI() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(123, s.nextInt(10));
+        assertEquals(456, s.nextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        assertEquals(38, s.nextInt(5));
+        try {
+            s.nextInt(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt(10));
+        assertEquals(23456, s.nextInt(10));
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt(10));
+        assertEquals(23456, s.nextInt(10));
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(102, s.nextInt(10));
+        try {
+            s.nextInt(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        assertEquals(162, s.nextInt(10));
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt(10));
+        assertEquals(23456, s.nextInt(10));
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("03456");
+        assertEquals(3456, s.nextInt(10));
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(3456, s.nextInt(10));
+
+        s = new Scanner("E3456");
+        assertEquals(930902, s.nextInt(16));
+        // The following test case fails on RI, because RI does not support
+        // letter as leading digit
+        s = new Scanner("E3,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(930902, s.nextInt(16));
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt(10));
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt(10));
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt(10));
+
+        /*
+         * There are three types of negative prefix all in all. '' '-' '(' There
+         * are three types of negative suffix all in all. '' '-' ')' '(' and ')'
+         * must be used togethor. Prefix '-' and suffix '-' must be used 
+         * exclusively.
+         */
+
+        /*
+         * According to Integer regular expression: Integer :: = ( [-+]? (*
+         * Numeral ) ) | LocalPositivePrefix Numeral LocalPositiveSuffix |
+         * LocalNegativePrefix Numeral LocalNegativeSuffix 123- should be
+         * recognized by scanner with locale ar_AE, (123) shouble be recognized
+         * by scanner with locale mk_MK. But this is not the case on RI.
+         */
+        s = new Scanner("-123 123- -123-");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(-123, s.nextInt(10));
+        // The following test case fails on RI
+        assertEquals(-123, s.nextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("-123 123-");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(-123, s.nextInt(10));
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        // Skip the un-recognizable token 123-.
+        assertEquals("123-", s.next());
+
+        // If the parameter radix is illegal, the following test cases fail on
+        // RI
+        try {
+            s.nextInt(Character.MIN_RADIX - 1);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+        try {
+            s.nextInt(Character.MAX_RADIX + 1);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextInt()
+     */
+    public void test_nextInt() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(123, s.nextInt());
+        assertEquals(456, s.nextInt());
+        try {
+            s.nextInt();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        s.useRadix(5);
+        assertEquals(38, s.nextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt());
+        assertEquals(23456, s.nextInt());
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt());
+        assertEquals(23456, s.nextInt());
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(102, s.nextInt());
+        s.useRadix(5);
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useRadix(10);
+        assertEquals(162, s.nextInt());
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextInt());
+        assertEquals(23456, s.nextInt());
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("03456");
+        assertEquals(3456, s.nextInt());
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(3456, s.nextInt());
+
+        s = new Scanner("E3456");
+        s.useRadix(16);
+        assertEquals(930902, s.nextInt());
+
+        // The following test case fails on RI, because RI does not support
+        // letter as leading digit
+        s = new Scanner("E3,456");
+        s.useLocale(Locale.ENGLISH);
+        s.useRadix(16);
+        assertEquals(930902, s.nextInt());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt());
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt());
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextInt());
+
+        /*
+         * There are three types of negative prefix all in all. '' '-' '(' There
+         * are three types of negative suffix all in all. '' '-' ')' '(' and ')'
+         * must be used togethor. Prefix '-' and suffix '-' must be used
+         * exclusively.
+         */
+
+        /*
+         * According to Integer regular expression: Integer :: = ( [-+]? (*
+         * Numeral ) ) | LocalPositivePrefix Numeral LocalPositiveSuffix |
+         * LocalNegativePrefix Numeral LocalNegativeSuffix 123- should be
+         * recognized by scanner with locale ar_AE, (123) shouble be recognized
+         * by scanner with locale mk_MK. But this is not the case on RI.
+         */
+        s = new Scanner("-123 123- -123-");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(-123, s.nextInt());
+        // The following test case fails on RI
+        assertEquals(-123, s.nextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("-123 123-");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(-123, s.nextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        // Skip the un-recognizable token 123-.
+        assertEquals("123-", s.next());
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextByte(int)
+     */
+    public void test_nextByteI() throws IOException {
+        s = new Scanner("123 126");
+        assertEquals(123, s.nextByte(10));
+        assertEquals(126, s.nextByte(10));
+        try {
+            s.nextByte(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 126");
+        assertEquals(38, s.nextByte(5));
+        try {
+            s.nextByte(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("1234");
+        try {
+            s.nextByte(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 12\u0666");
+        assertEquals(102, s.nextByte(10));
+        try {
+            s.nextByte(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        assertEquals(126, s.nextByte(10));
+
+        s = new Scanner("012");
+        assertEquals(12, s.nextByte(10));
+
+        s = new Scanner("E");
+        assertEquals(14, s.nextByte(16));
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("100");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(100, s.nextByte(10));
+
+        s = new Scanner("1\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(100, s.nextByte(10));
+        
+        s = new Scanner("1\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(100, s.nextByte(10));
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(-123, s.nextByte(10));
+       
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(-123, s.nextByte(10));
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextByte()
+     */
+    public void test_nextByte() throws IOException {
+        s = new Scanner("123 126");
+        assertEquals(123, s.nextByte());
+        assertEquals(126, s.nextByte());
+        try {
+            s.nextByte();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 126");
+        s.useRadix(5);
+        assertEquals(38, s.nextByte());
+        try {
+            s.nextByte();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("1234");
+        try {
+            s.nextByte();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 12\u0666");
+        assertEquals(102, s.nextByte());
+        s.useRadix(5);
+        try {
+            s.nextByte();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useRadix(10);
+        assertEquals(126, s.nextByte());
+
+        s = new Scanner("012");
+        assertEquals(12, s.nextByte());
+
+        s = new Scanner("E");
+        s.useRadix(16);
+        assertEquals(14, s.nextByte());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("100");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(100, s.nextByte());
+
+        s = new Scanner("1\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(100, s.nextByte());
+        
+        s = new Scanner("1\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(100, s.nextByte());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(-123, s.nextByte());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(-123, s.nextByte());
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextFloat()
+     */
+    public void test_nextFloat() throws IOException {
+        s = new Scanner("123 45\u0666. 123.4 .123 ");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals((float)123.0, s.nextFloat());
+        assertEquals((float)456.0, s.nextFloat());
+        assertEquals((float)123.4, s.nextFloat());
+        assertEquals((float)0.123, s.nextFloat());
+        try {
+            s.nextFloat();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals((float)123.4, s.nextFloat());
+        assertEquals((float)-456.7, s.nextFloat());
+        assertEquals((float)123456.789, s.nextFloat());
+        try {
+            s.nextFloat();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // Scientific notation
+        s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals((float)1.234E12, s.nextFloat());
+        assertEquals((float)-4.567E14, s.nextFloat());
+        assertEquals((float)1.23456789E-5, s.nextFloat());
+
+        s = new Scanner("NaN Infinity -Infinity");
+        assertEquals(Float.NaN, s.nextFloat());
+        assertEquals(Float.POSITIVE_INFINITY, s.nextFloat());
+        assertEquals(Float.NEGATIVE_INFINITY, s.nextFloat());
+
+        String str=String.valueOf(Float.MAX_VALUE*2);
+        s=new Scanner(str);
+        assertEquals(Float.POSITIVE_INFINITY,s.nextFloat());
+        
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals((float)23456.0, s.nextFloat());
+        s.useLocale(Locale.GERMANY);
+        assertEquals((float)23.456, s.nextFloat());
+
+        s = new Scanner("23.456 23.456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals((float)23.456, s.nextFloat());
+        s.useLocale(Locale.GERMANY);
+        assertEquals((float)23456.0, s.nextFloat());
+
+        s = new Scanner("23,456.7 23.456,7");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals((float)23456.7, s.nextFloat());
+        s.useLocale(Locale.GERMANY);
+        assertEquals((float)23456.7, s.nextFloat());
+
+        s = new Scanner("-123.4 123.4- -123.4-");
+        s.useLocale(new Locale("ar", "AE"));
+        // FIXME
+//        assertEquals((float)-123.4, s.nextFloat());
+//        //The following test case fails on RI
+//        assertEquals((float)-123.4, s.nextFloat());
+        try {
+            s.nextFloat();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("123- -123");
+        s.useLocale(new Locale("mk", "MK"));
+        try {
+            s.nextFloat();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        // Skip the un-recognizable token 123-.
+        assertEquals("123-", s.next());
+        assertEquals((float)-123.0, s.nextFloat());
+
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextBigInteger(int)
+     */
+    public void test_nextBigIntegerI() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(new BigInteger("123"), s.nextBigInteger(10));
+        assertEquals(new BigInteger("456"), s.nextBigInteger(10));
+        try {
+            s.nextBigInteger(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        assertEquals(new BigInteger("38"), s.nextBigInteger(5));
+        try {
+            s.nextBigInteger(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextBigInteger(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextBigInteger(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(new BigInteger("102"), s.nextBigInteger(10));
+        try {
+            s.nextBigInteger(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        assertEquals(new BigInteger("162"), s.nextBigInteger(10));
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        try {
+            s.nextBigInteger(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        try {
+            s.nextBigInteger(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertEquals(new BigInteger("3456"), s.nextBigInteger(10));
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(new BigInteger("3456"), s.nextBigInteger(10));
+
+        s = new Scanner("E34");
+        assertEquals(new BigInteger("3636"), s.nextBigInteger(16));
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(new BigInteger("-123"), s.nextBigInteger(10));
+       
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(new BigInteger("-123"), s.nextBigInteger(10));
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextBigInteger()
+     */
+    public void test_nextBigInteger() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(new BigInteger("123"), s.nextBigInteger());
+        assertEquals(new BigInteger("456"), s.nextBigInteger());
+        try {
+            s.nextBigInteger();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        s.useRadix(5);
+        assertEquals(new BigInteger("38"), s.nextBigInteger());
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(new BigInteger("102"), s.nextBigInteger());
+        s.useRadix(5);
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useRadix(10);
+        assertEquals(new BigInteger("162"), s.nextBigInteger());
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertEquals(new BigInteger("3456"), s.nextBigInteger());
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(new BigInteger("3456"), s.nextBigInteger());
+
+        s = new Scanner("E34");
+        s.useRadix(16);
+        assertEquals(new BigInteger("3636"), s.nextBigInteger());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(new BigInteger("12300"), s.nextBigInteger());
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(new BigInteger("12300"), s.nextBigInteger());
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(new BigInteger("12300"), s.nextBigInteger());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(new BigInteger("-123"), s.nextBigInteger());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(new BigInteger("-123"), s.nextBigInteger());
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextShort(int)
+     */
+    public void test_nextShortI() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(123, s.nextShort(10));
+        assertEquals(456, s.nextShort(10));
+        try {
+            s.nextShort(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        assertEquals(38, s.nextShort(5));
+        try {
+            s.nextShort(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789");
+        try {
+            s.nextShort(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextShort(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextShort(10));
+        assertEquals(23456, s.nextShort(10));
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextShort(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextShort(10));
+        assertEquals(23456, s.nextShort(10));
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(102, s.nextShort(10));
+        try {
+            s.nextShort(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        assertEquals(162, s.nextShort(10));
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        try {
+            s.nextShort(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextShort(10));
+        assertEquals(23456, s.nextShort(10));
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        try {
+            s.nextShort(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertEquals(3456, s.nextShort(10));
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(3456, s.nextShort(10));
+
+        s = new Scanner("E34");
+        assertEquals(3636, s.nextShort(16));
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextShort(10));
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextShort(10));
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextShort(10));
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(-123, s.nextShort(10));
+       
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(-123, s.nextShort(10));
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextShort()
+     */
+    public void test_nextShort() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(123, s.nextShort());
+        assertEquals(456, s.nextShort());
+        try {
+            s.nextShort();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        s.useRadix(5);
+        assertEquals(38, s.nextShort());
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789");
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextShort());
+        assertEquals(23456, s.nextShort());
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextShort());
+        assertEquals(23456, s.nextShort());
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(102, s.nextShort());
+        s.useRadix(5);
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useRadix(10);
+        assertEquals(162, s.nextShort());
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextShort());
+        assertEquals(23456, s.nextShort());
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertEquals(3456, s.nextShort());
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(3456, s.nextShort());
+
+        s = new Scanner("E34");
+        s.useRadix(16);
+        assertEquals(3636, s.nextShort());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextShort());
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextShort());
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextShort());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(-123, s.nextShort());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(-123, s.nextShort());
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextLong(int)
+     */
+    public void test_nextLongI() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(123, s.nextLong(10));
+        assertEquals(456, s.nextLong(10));
+        try {
+            s.nextLong(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        assertEquals(38, s.nextLong(5));
+        try {
+            s.nextLong(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        try {
+            s.nextLong(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextLong(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextLong(10));
+        assertEquals(23456, s.nextLong(10));
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextLong(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextLong(10));
+        assertEquals(23456, s.nextLong(10));
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(102, s.nextLong(10));
+        try {
+            s.nextLong(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        assertEquals(162, s.nextLong(10));
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        try {
+            s.nextLong(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextLong(10));
+        assertEquals(23456, s.nextLong(10));
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        try {
+            s.nextLong(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertEquals(3456, s.nextLong(10));
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(3456, s.nextLong(10));
+
+        s = new Scanner("E34");
+        assertEquals(3636, s.nextLong(16));
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextLong(10));
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextLong(10));
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextLong(10));
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(-123, s.nextLong(10));
+       
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(-123, s.nextLong(10));
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextLong()
+     */
+    public void test_nextLong() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(123, s.nextLong());
+        assertEquals(456, s.nextLong());
+        try {
+            s.nextLong();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        s.useRadix(5);
+        assertEquals(38, s.nextLong());
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextLong());
+        assertEquals(23456, s.nextLong());
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextLong());
+        assertEquals(23456, s.nextLong());
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(102, s.nextLong());
+        s.useRadix(5);
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useRadix(10);
+        assertEquals(162, s.nextLong());
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertEquals(23456, s.nextLong());
+        assertEquals(23456, s.nextLong());
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertEquals(3456, s.nextLong());
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(3456, s.nextLong());
+
+        s = new Scanner("E34");
+        s.useRadix(16);
+        assertEquals(3636, s.nextLong());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextLong());
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextLong());
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertEquals(12300, s.nextLong());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertEquals(-123, s.nextLong());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertEquals(-123, s.nextLong());
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNext()
+     */
+    public void test_hasNext() throws IOException {
+        s = new Scanner("1##2").useDelimiter("\\#");
+        assertTrue(s.hasNext());
+        assertEquals("1", s.next());
+        assertEquals("", s.next());
+        assertEquals("2", s.next());
+        assertFalse(s.hasNext());
+        s.close();
+        try {
+            s.hasNext();
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+
+        s = new Scanner("1( )2( )").useDelimiter("\\( \\)");
+        assertTrue(s.hasNext());
+        assertTrue(s.hasNext());
+        assertEquals("1", s.next());
+        assertEquals("2", s.next());
+
+        s = new Scanner("1 2  ").useDelimiter("( )");
+        assertEquals("1", s.next());
+        assertEquals("2", s.next());
+        assertTrue(s.hasNext());
+        assertEquals("", s.next());
+
+        s = new Scanner("1\n2  ");
+        assertEquals("1", s.next());
+        assertTrue(s.hasNext());
+        assertEquals("2", s.next());
+        assertFalse(s.hasNext());
+        // test boundary case
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("1'\n'2  ");
+        assertEquals("1'", s.next());
+        assertTrue(s.hasNext());
+        assertEquals("'2", s.next());
+        assertFalse(s.hasNext());
+        // test boundary case
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("  ");
+        assertFalse(s.hasNext());
+
+        // test socket inputStream
+
+        os.write("1 2".getBytes());
+        serverSocket.close();
+
+        s = new Scanner(client);
+        assertEquals("1", s.next());
+        assertTrue(s.hasNext());
+        assertEquals("2", s.next());
+        assertFalse(s.hasNext());
+        try {
+            s.next();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNext(Pattern)
+     */
+    public void test_hasNextLPattern() throws IOException {
+        Pattern pattern;
+        s = new Scanner("aab@2@abb@").useDelimiter("\\@");
+        pattern = Pattern.compile("a*b");
+        assertTrue(s.hasNext(pattern));
+        assertEquals("aab", s.next(pattern));
+        assertFalse(s.hasNext(pattern));
+        try {
+            s.next(pattern);
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("word ? ");
+        pattern = Pattern.compile("\\w+");
+        assertTrue(s.hasNext(pattern));
+        assertEquals("word", s.next(pattern));
+        assertFalse(s.hasNext(pattern));
+        try {
+            s.next(pattern);
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("word1 WorD2  ");
+        pattern = Pattern.compile("\\w+");
+        assertTrue(s.hasNext(pattern));
+        assertEquals("word1", s.next(pattern));
+        assertTrue(s.hasNext(pattern));
+        assertEquals("WorD2", s.next(pattern));
+        assertFalse(s.hasNext(pattern));
+        try {
+            s.next(pattern);
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("word1 WorD2  ");
+        pattern = Pattern.compile("\\w+");
+        try {
+            s.hasNext((Pattern) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        s.close();
+        try {
+            s.hasNext(pattern);
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+        
+        // test socket inputStream
+        os.write("aab b".getBytes());
+        serverSocket.close();
+
+        s = new Scanner(client);
+        pattern = Pattern.compile("a+b");
+        assertTrue(s.hasNext(pattern));
+        assertEquals("aab", s.next(pattern));
+        assertFalse(s.hasNext(pattern));
+        try {
+            s.next(pattern);
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNext(String)
+     */
+    public void test_hasNextLString() throws IOException {
+        s = new Scanner("aab@2@abb@").useDelimiter("\\@");
+        try {
+            s.hasNext((String)null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        
+        s = new Scanner("aab*b*").useDelimiter("\\*");
+        assertTrue(s.hasNext("a+b"));
+        assertEquals("aab", s.next("a+b"));
+        assertFalse(s.hasNext("a+b"));
+        try {
+            s.next("a+b");
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.close();
+        try {
+            s.hasNext("a+b");
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+
+        s = new Scanner("WORD ? ");
+        assertTrue(s.hasNext("\\w+"));
+        assertEquals("WORD", s.next("\\w+"));
+        assertFalse(s.hasNext("\\w+"));
+        try {
+            s.next("\\w+");
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("word1 word2  ");
+        assertEquals("word1", s.next("\\w+"));
+        assertEquals("word2", s.next("\\w+"));
+        // test boundary case
+        try {
+            s.next("\\w+");
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // test socket inputStream
+
+        os.write("aab 2".getBytes());
+        serverSocket.close();
+
+        s = new Scanner(client);
+        assertTrue(s.hasNext("a*b"));
+        assertEquals("aab", s.next("a*b"));
+        assertFalse(s.hasNext("a*b"));
+        try {
+            s.next("a*b");
+            fail("should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextBoolean()
+     */
+    public void test_hasNextBoolean() throws IOException {
+
+        s = new Scanner("TRue");
+        assertTrue(s.hasNextBoolean());
+        assertTrue(s.nextBoolean());
+
+        s = new Scanner("tRue false");
+        assertTrue(s.hasNextBoolean());
+        assertTrue(s.nextBoolean());
+        assertTrue(s.hasNextBoolean());
+        assertFalse(s.nextBoolean());
+
+        s = new Scanner("");
+        assertFalse(s.hasNextBoolean());
+
+        // test socket inputStream
+
+        os.write("true false ".getBytes());
+        serverSocket.close();
+
+        s = new Scanner(client);
+        assertTrue(s.hasNextBoolean());
+        assertTrue(s.nextBoolean());
+
+        // ues '*' as delimiter
+        s = new Scanner("true**false").useDelimiter("\\*");
+        assertTrue(s.hasNextBoolean());
+        assertTrue(s.nextBoolean());
+        assertFalse(s.hasNextBoolean());
+        try {
+            s.nextBoolean();
+            fail("should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("false( )").useDelimiter("\\( \\)");
+        assertTrue(s.hasNextBoolean());
+        assertFalse(s.nextBoolean());
+        assertFalse(s.hasNextBoolean());
+
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextByte(int)
+     */
+    public void test_hasNextByteI() throws IOException {
+        s = new Scanner("123 126");
+        assertTrue(s.hasNextByte(10));
+        assertEquals(123, s.nextByte(10));
+        assertTrue(s.hasNextByte(10));
+        assertEquals(126, s.nextByte(10));
+        assertFalse(s.hasNextByte(10));
+        try {
+            s.nextByte(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 126");
+        assertTrue(s.hasNextByte(5));
+        assertEquals(38, s.nextByte(5));
+        assertFalse(s.hasNextByte(5));
+        try {
+            s.nextByte(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("1234");
+        assertFalse(s.hasNextByte(10));
+        try {
+            s.nextByte(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 12\u0666");
+        assertTrue(s.hasNextByte(10));
+        assertEquals(102, s.nextByte(10));
+        assertFalse(s.hasNextByte(5));
+        try {
+            s.nextByte(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        assertTrue(s.hasNextByte(10));
+        assertEquals(126, s.nextByte(10));
+
+        s = new Scanner("012");
+        assertTrue(s.hasNextByte(10));
+        assertEquals(12, s.nextByte(10));
+
+        s = new Scanner("E");
+        assertTrue(s.hasNextByte(16));
+        assertEquals(14, s.nextByte(16));
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("100");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextByte(10));
+        assertEquals(100, s.nextByte(10));
+
+        s = new Scanner("1\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextByte(10));
+        assertEquals(100, s.nextByte(10));
+        
+        s = new Scanner("1\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextByte(10));
+        assertEquals(100, s.nextByte(10));
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextByte(10));
+        assertEquals(-123, s.nextByte(10));
+       
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextByte(10));
+        assertEquals(-123, s.nextByte(10));
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextByte(int)
+     */
+    public void test_hasNextByteI_cache() throws IOException{
+        //regression for HARMONY-2063
+    	s = new Scanner("123 45");
+		assertTrue(s.hasNextByte(8));
+		assertEquals(83, s.nextByte());
+		assertEquals(45, s.nextByte());
+
+		s = new Scanner("123 45");
+		assertTrue(s.hasNextByte(10));
+		assertTrue(s.hasNextByte(8));
+		assertEquals(83, s.nextByte());
+		assertEquals(45, s.nextByte());
+
+		s = new Scanner("-123 -45");
+		assertTrue(s.hasNextByte(8));
+		assertEquals(-123, s.nextInt());
+		assertEquals(-45, s.nextByte());
+		
+		s = new Scanner("123 45");
+		assertTrue(s.hasNextByte());
+		s.close();
+		try {
+			s.nextByte();
+			fail("Should throw IllegalStateException");
+		} catch (IllegalStateException e) {
+			// expected
+		}
+    }
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextByte()
+     */
+    public void test_hasNextByte() throws IOException {
+        s = new Scanner("123 126");
+        assertTrue(s.hasNextByte());
+        assertEquals(123, s.nextByte());
+        assertTrue(s.hasNextByte());
+        assertEquals(126, s.nextByte());
+        assertFalse(s.hasNextByte());
+        try {
+            s.nextByte();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 126");
+        s.useRadix(5);
+        assertTrue(s.hasNextByte());
+        assertEquals(38, s.nextByte());
+        assertFalse(s.hasNextByte());
+        try {
+            s.nextByte();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("1234");
+        assertFalse(s.hasNextByte());
+        try {
+            s.nextByte();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 12\u0666");
+        assertTrue(s.hasNextByte());
+        assertEquals(102, s.nextByte());
+        s.useRadix(5);
+        assertFalse(s.hasNextByte());
+        try {
+            s.nextByte();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useRadix(10);
+        assertTrue(s.hasNextByte());
+        assertEquals(126, s.nextByte());
+
+        s = new Scanner("012");
+        assertEquals(12, s.nextByte());
+
+        s = new Scanner("E");
+        s.useRadix(16);
+        assertTrue(s.hasNextByte());
+        assertEquals(14, s.nextByte());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("100");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextByte());
+        assertEquals(100, s.nextByte());
+
+        s = new Scanner("1\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextByte());
+        assertEquals(100, s.nextByte());
+        
+        s = new Scanner("1\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextByte());
+        assertEquals(100, s.nextByte());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextByte());
+        assertEquals(-123, s.nextByte());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextByte());
+        assertEquals(-123, s.nextByte());
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextBigInteger(int)
+     */
+    public void test_hasNextBigIntegerI() throws IOException {
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("123"), s.nextBigInteger(10));
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("456"), s.nextBigInteger(10));
+        assertFalse(s.hasNextBigInteger(10));
+        try {
+            s.nextBigInteger(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextBigInteger(5));
+        assertEquals(new BigInteger("38"), s.nextBigInteger(5));
+        assertFalse(s.hasNextBigInteger(5));
+        try {
+            s.nextBigInteger(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextBigInteger(10));
+        try {
+            s.nextBigInteger(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextBigInteger(10));
+        try {
+            s.nextBigInteger(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("102"), s.nextBigInteger(10));
+        assertFalse(s.hasNextBigInteger(5));
+        try {
+            s.nextBigInteger(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("162"), s.nextBigInteger(10));
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        assertFalse(s.hasNextBigInteger(10));
+        try {
+            s.nextBigInteger(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        assertFalse(s.hasNextBigInteger(10));
+        try {
+            s.nextBigInteger(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("3456"), s.nextBigInteger(10));
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("3456"), s.nextBigInteger(10));
+
+        s = new Scanner("E34");
+        assertTrue(s.hasNextBigInteger(16));
+        assertEquals(new BigInteger("3636"), s.nextBigInteger(16));
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("-123"), s.nextBigInteger(10));
+       
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextBigInteger(10));
+        assertEquals(new BigInteger("-123"), s.nextBigInteger(10));
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextBigInteger(int)
+     */
+    public void test_hasNextBigIntegerI_cache() throws IOException {
+        //regression for HARMONY-2063
+    	s = new Scanner("123 123456789123456789");
+		assertTrue(s.hasNextBigInteger(16));
+		assertEquals(new BigInteger("291"), s.nextBigInteger());
+		assertEquals(new BigInteger("123456789123456789"), s.nextBigInteger());
+
+		s = new Scanner("123456789123456789 456");
+		assertTrue(s.hasNextBigInteger(16));
+		assertTrue(s.hasNextBigInteger(10));
+		assertEquals(new BigInteger("123456789123456789"), s.nextBigInteger());
+		assertEquals(new BigInteger("456"), s.nextBigInteger());
+
+		s = new Scanner("-123 -123456789123456789");
+		assertTrue(s.hasNextBigInteger(8));
+		assertEquals(-123, s.nextShort());
+		assertEquals(new BigInteger("-123456789123456789"), s.nextBigInteger());
+		
+		s = new Scanner("123 456");
+		assertTrue(s.hasNextBigInteger());
+		s.close();
+		try {
+			s.nextBigInteger();
+			fail("Should throw IllegalStateException");
+		} catch (IllegalStateException e) {
+			// expected
+		}
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextBigInteger()
+     */
+    public void test_hasNextBigInteger() throws IOException {
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("123"), s.nextBigInteger());
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("456"), s.nextBigInteger());
+        assertFalse(s.hasNextBigInteger());
+        try {
+            s.nextBigInteger();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        s.useRadix(5);
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("38"), s.nextBigInteger());
+        assertFalse(s.hasNextBigInteger());
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextBigInteger());
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextBigInteger());
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(new BigInteger("102"), s.nextBigInteger());
+        s.useRadix(5);
+        assertFalse(s.hasNextBigInteger());
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useRadix(10);
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("162"), s.nextBigInteger());
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        assertFalse(s.hasNextBigInteger());
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        assertFalse(s.hasNextBigInteger());
+        try {
+            s.nextBigInteger();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("3456"), s.nextBigInteger());
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("3456"), s.nextBigInteger());
+
+        s = new Scanner("E34");
+        s.useRadix(16);
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("3636"), s.nextBigInteger());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("12300"), s.nextBigInteger());
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("12300"), s.nextBigInteger());
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("12300"), s.nextBigInteger());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("-123"), s.nextBigInteger());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextBigInteger());
+        assertEquals(new BigInteger("-123"), s.nextBigInteger());
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextInt(int)
+     */
+    public void test_hasNextIntI() throws IOException {
+        s = new Scanner("123 456");
+        assertEquals(123, s.nextInt(10));
+        assertTrue(s.hasNextInt(10));
+        assertEquals(456, s.nextInt(10));
+        assertFalse(s.hasNextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextInt(5));
+        assertEquals(38, s.nextInt(5));
+        assertFalse(s.hasNextInt(5));
+        try {
+            s.nextInt(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        assertFalse(s.hasNextInt(10));
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextInt(10));
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextInt(10));
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextInt(10));
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextInt(10));
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06662");
+        assertTrue(s.hasNextInt(10));
+        assertFalse(s.hasNextInt(5));
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666");
+        s.useLocale(Locale.CHINESE);
+        assertFalse(s.hasNextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextInt(10));
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        assertFalse(s.hasNextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("03456");
+        assertTrue(s.hasNextInt(10));
+        assertEquals(3456, s.nextInt(10));
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextInt(10));
+        assertEquals(3456, s.nextInt(10));
+
+        s = new Scanner("E3456");
+        assertTrue(s.hasNextInt(16));
+        assertEquals(930902, s.nextInt(16));
+        // The following test case fails on RI, because RI does not support
+        // letter as leading digit
+        s = new Scanner("E3,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextInt(16));
+        assertEquals(930902, s.nextInt(16));
+
+        // If parameter radix is illegal, the following test case fails on RI
+        try {
+            s.hasNextInt(Character.MIN_RADIX - 1);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt(10));
+        assertEquals(12300, s.nextInt(10));
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt(10));
+        assertEquals(12300, s.nextInt(10));
+
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt(10));
+        assertEquals(12300, s.nextInt(10));
+
+        /*
+         * There are three types of negative prefix all in all. '' '-' '(' There
+         * are three types of negative suffix all in all. '' '-' ')' '(' and ')'
+         * must be used togethor. Prefix '-' and suffix '-' must be used 
+         * exclusively.
+         */
+
+        /*
+         * According to Integer regular expression: Integer :: = ( [-+]? (*
+         * Numeral ) ) | LocalPositivePrefix Numeral LocalPositiveSuffix |
+         * LocalNegativePrefix Numeral LocalNegativeSuffix 123- should be
+         * recognized by scanner with locale ar_AE, (123) shouble be recognized
+         * by scanner with locale mk_MK. But this is not the case on RI.
+         */
+        s = new Scanner("-123 123- -123-");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextInt(10));
+        assertEquals(-123, s.nextInt(10));
+        // The following test case fails on RI
+        assertTrue(s.hasNextInt(10));
+        assertEquals(-123, s.nextInt(10));
+        assertFalse(s.hasNextInt(10));
+        try {
+            s.nextInt(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("-123 123-");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextInt(10));
+        assertEquals(-123, s.nextInt(10));
+        assertFalse(s.hasNextInt(10));
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        // Skip the un-recognizable token 123-.
+        assertEquals("123-", s.next());
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextInt(int)
+     */
+    public void test_hasNextIntI_cache() throws IOException {
+        //regression for HARMONY-2063
+    	s = new Scanner("123 456");
+		assertTrue(s.hasNextInt(16));
+		assertEquals(291, s.nextInt(10));
+		assertEquals(456, s.nextInt());
+
+		s = new Scanner("123 456");
+		assertTrue(s.hasNextInt(16));
+		assertTrue(s.hasNextInt(8));
+		assertEquals(83, s.nextInt());
+		assertEquals(456, s.nextInt());
+
+		s = new Scanner("-123 -456 -789");
+		assertTrue(s.hasNextInt(8));
+		assertEquals(-123, s.nextShort());
+		assertEquals(-456, s.nextInt());
+		assertTrue(s.hasNextShort(16));
+		assertEquals(-789, s.nextInt());
+		
+		s = new Scanner("123 456");
+		assertTrue(s.hasNextInt());
+		s.close();
+		try {
+			s.nextInt();
+			fail("Should throw IllegalStateException");
+		} catch (IllegalStateException e) {
+			// expected
+		}
+    }
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextInt()
+     */
+    public void test_hasNextInt() throws IOException {
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextInt());
+        assertEquals(123, s.nextInt());
+        assertEquals(456, s.nextInt());
+        assertFalse(s.hasNextInt());
+        try {
+            s.nextInt();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        s.useRadix(5);
+        assertTrue(s.hasNextInt());
+        assertEquals(38, s.nextInt());
+        assertFalse(s.hasNextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        assertFalse(s.hasNextInt());
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextInt());
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextInt());
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextInt());
+        s.useLocale(new Locale("it", "CH"));
+        assertTrue(s.hasNextInt());
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06662");
+        s.useRadix(5);
+        assertFalse(s.hasNextInt());
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666");
+        s.useLocale(Locale.CHINESE);
+        assertFalse(s.hasNextInt());
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextInt());
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        assertFalse(s.hasNextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("03456");
+        assertTrue(s.hasNextInt());
+        assertEquals(3456, s.nextInt());
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(3456, s.nextInt());
+
+        s = new Scanner("E3456");
+        s.useRadix(16);
+        assertTrue(s.hasNextInt());
+        assertEquals(930902, s.nextInt());
+
+        // The following test case fails on RI, because RI does not support
+        // letter as leading digit
+        s = new Scanner("E3,456");
+        s.useLocale(Locale.ENGLISH);
+        s.useRadix(16);
+        assertTrue(s.hasNextInt());
+        assertEquals(930902, s.nextInt());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt());
+        assertEquals(12300, s.nextInt());
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt());
+        assertEquals(12300, s.nextInt());
+
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextInt());
+        assertEquals(12300, s.nextInt());
+
+        /*
+         * There are three types of negative prefix all in all. '' '-' '(' There
+         * are three types of negative suffix all in all. '' '-' ')' '(' and ')'
+         * must be used togethor. Prefix '-' and suffix '-' must be used 
+         * exclusively.
+         */
+
+        /*
+         * According to Integer regular expression: Integer :: = ( [-+]? (*
+         * Numeral ) ) | LocalPositivePrefix Numeral LocalPositiveSuffix |
+         * LocalNegativePrefix Numeral LocalNegativeSuffix 123- should be
+         * recognized by scanner with locale ar_AE, (123) shouble be recognized
+         * by scanner with locale mk_MK. But this is not the case on RI.
+         */
+        s = new Scanner("-123 123- -123-");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextInt());
+        assertEquals(-123, s.nextInt());
+        // The following test case fails on RI
+        assertTrue(s.hasNextInt());
+        assertEquals(-123, s.nextInt());
+        assertFalse(s.hasNextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+
+        s = new Scanner("-123 123-");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextInt());
+        assertEquals(-123, s.nextInt());
+        try {
+            s.nextInt();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // expected
+        }
+        // Skip the un-recognizable token 123-.
+        assertEquals("123-", s.next());
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextFloat()
+     */
+    public void test_hasNextFloat() throws IOException {
+        s = new Scanner("123 45\u0666. 123.4 .123 ");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)123.0, s.nextFloat());
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)456.0, s.nextFloat());
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)123.4, s.nextFloat());
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)0.123, s.nextFloat());
+        assertFalse(s.hasNextFloat());
+        try {
+            s.nextFloat();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)123.4, s.nextFloat());
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)-456.7, s.nextFloat());
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)123456.789, s.nextFloat());
+        assertFalse(s.hasNextFloat());
+        try {
+            s.nextFloat();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // Scientific notation
+        s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)1.234E12, s.nextFloat());
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)-4.567E14, s.nextFloat());
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)1.23456789E-5, s.nextFloat());
+
+        s = new Scanner("NaN Infinity -Infinity");
+        assertTrue(s.hasNextFloat());
+        assertEquals(Float.NaN, s.nextFloat());
+        assertTrue(s.hasNextFloat());
+        assertEquals(Float.POSITIVE_INFINITY, s.nextFloat());
+        assertTrue(s.hasNextFloat());
+        assertEquals(Float.NEGATIVE_INFINITY, s.nextFloat());
+
+        String str=String.valueOf(Float.MAX_VALUE*2);
+        s=new Scanner(str);
+        assertTrue(s.hasNextFloat());
+        assertEquals(Float.POSITIVE_INFINITY,s.nextFloat());
+        
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)23456.0, s.nextFloat());
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)23.456, s.nextFloat());
+
+        s = new Scanner("23.456 23.456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)23.456, s.nextFloat());
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)23456.0, s.nextFloat());
+
+        s = new Scanner("23,456.7 23.456,7");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)23456.7, s.nextFloat());
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)23456.7, s.nextFloat());
+
+        //FIXME
+//        s = new Scanner("-123.4 123.4- -123.4-");
+//        s.useLocale(new Locale("ar", "AE"));
+//        assertTrue(s.hasNextFloat());
+//        assertEquals((float)-123.4, s.nextFloat());
+//        //The following test case fails on RI
+//        assertTrue(s.hasNextFloat());
+//        assertEquals((float)-123.4, s.nextFloat());
+//        try {
+//            s.nextFloat();
+//            fail("Should throw InputMismatchException");
+//        } catch (InputMismatchException e) {
+//            // Expected
+//        }
+
+        s = new Scanner("123- -123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertFalse(s.hasNextFloat());
+        try {
+            s.nextFloat();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        // Skip the un-recognizable token 123-.
+        assertEquals("123-", s.next());
+        assertTrue(s.hasNextFloat());
+        assertEquals((float)-123.0, s.nextFloat());
+        
+        s = new Scanner("+123.4 -456.7");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextFloat());
+        s.close();
+        try{
+        	s.nextFloat();
+        	fail("Should throw IllegalStateException");
+        }catch(IllegalStateException e){
+        	//expected
+        }
+
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextShort(int)
+     */
+    public void test_hasNextShortI() throws IOException {
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextShort(10));
+        assertEquals(123, s.nextShort(10));
+        assertTrue(s.hasNextShort(10));
+        assertEquals(456, s.nextShort(10));
+        assertFalse(s.hasNextShort(10));
+        try {
+            s.nextShort(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextShort(5));
+        assertEquals(38, s.nextShort(5));
+        assertFalse(s.hasNextShort(5));
+        try {
+            s.nextShort(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789");
+        assertFalse(s.hasNextShort(10));
+        try {
+            s.nextShort(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextShort(10));
+        try {
+            s.nextShort(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextShort(10));
+        assertEquals(23456, s.nextInt(10));
+        assertTrue(s.hasNextShort(10));
+        assertEquals(23456, s.nextInt(10));
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextShort(10));
+        try {
+            s.nextShort(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextShort(10));
+        assertEquals(23456, s.nextShort(10));
+        assertTrue(s.hasNextShort(10));
+        assertEquals(23456, s.nextShort(10));
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertTrue(s.hasNextShort(10));
+        assertEquals(102, s.nextShort(10));
+        assertFalse(s.hasNextShort(5));
+        try {
+            s.nextShort(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        assertTrue(s.hasNextShort(10));
+        assertEquals(162, s.nextShort(10));
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        assertFalse(s.hasNextShort(10));
+        try {
+            s.nextShort(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextShort(10));
+        assertEquals(23456, s.nextShort(10));
+        assertTrue(s.hasNextShort(10));
+        assertEquals(23456, s.nextShort(10));
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        assertFalse(s.hasNextShort(10));
+        try {
+            s.nextShort(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertTrue(s.hasNextShort(10));
+        assertEquals(3456, s.nextShort(10));
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextShort(10));
+        assertEquals(3456, s.nextShort(10));
+
+        s = new Scanner("E34");
+        assertTrue(s.hasNextShort(16));
+        assertEquals(3636, s.nextShort(16));
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextShort(10));
+        assertEquals(12300, s.nextShort(10));
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextShort(10));
+        assertEquals(12300, s.nextShort(10));
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextShort(10));
+        assertEquals(12300, s.nextShort(10));
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextShort(10));
+        assertEquals(-123, s.nextShort(10));
+       
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextShort(10));
+        assertEquals(-123, s.nextShort(10));
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextShort()
+     */
+    public void test_hasNextShort() throws IOException {
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextShort());
+        assertEquals(123, s.nextShort());
+        assertTrue(s.hasNextShort());
+        assertEquals(456, s.nextShort());
+        assertFalse(s.hasNextShort());
+        try {
+            s.nextShort();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        s.useRadix(5);
+        assertTrue(s.hasNextShort());
+        assertEquals(38, s.nextShort());
+        assertFalse(s.hasNextShort());
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789");
+        assertFalse(s.hasNextShort());
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextShort());
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextShort());
+        assertEquals(23456, s.nextShort());
+        assertTrue(s.hasNextShort());
+        assertEquals(23456, s.nextShort());
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextShort());
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextShort());
+        assertEquals(23456, s.nextShort());
+        assertTrue(s.hasNextShort());
+        assertEquals(23456, s.nextShort());
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(102, s.nextShort());
+        s.useRadix(5);
+        assertFalse(s.hasNextShort());
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useRadix(10);
+        assertTrue(s.hasNextShort());
+        assertEquals(162, s.nextShort());
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        assertFalse(s.hasNextShort());
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextShort());
+        assertEquals(23456, s.nextShort());
+        assertTrue(s.hasNextShort());
+        assertEquals(23456, s.nextShort());
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        assertFalse(s.hasNextShort());
+        try {
+            s.nextShort();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertTrue(s.hasNextShort());
+        assertEquals(3456, s.nextShort());
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextShort());
+        assertEquals(3456, s.nextShort());
+
+        s = new Scanner("E34");
+        s.useRadix(16);
+        assertTrue(s.hasNextShort());
+        assertEquals(3636, s.nextShort());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextShort());
+        assertEquals(12300, s.nextShort());
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextShort());
+        assertEquals(12300, s.nextShort());
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextShort());
+        assertEquals(12300, s.nextShort());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextShort());
+        assertEquals(-123, s.nextShort());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextShort());
+        assertEquals(-123, s.nextShort());
+    }
+    
+    /**
+	 * @throws IOException
+	 * @tests java.util.Scanner#hasNextShort(int)
+	 */
+	public void test_hasNextShortI_cache() throws IOException {
+        //regression for HARMONY-2063
+		s = new Scanner("123 456");
+		assertTrue(s.hasNextShort(16));
+		assertEquals(291, s.nextShort());
+		assertEquals(456, s.nextShort());
+
+		s = new Scanner("123 456");
+		assertTrue(s.hasNextShort(16));
+		assertTrue(s.hasNextShort(8));
+		assertEquals(83, s.nextShort());
+		assertEquals(456, s.nextShort());
+
+		s = new Scanner("-123 -456 -789");
+		assertTrue(s.hasNextShort(8));
+		assertEquals(-123, s.nextInt());
+		assertEquals(-456, s.nextShort());
+		assertTrue(s.hasNextInt(16));
+		assertEquals(-789, s.nextShort());
+		
+		s = new Scanner("123 456");
+		assertTrue(s.hasNextShort());
+		s.close();
+		try {
+			s.nextShort();
+			fail("Should throw IllegalStateException");
+		} catch (IllegalStateException e) {
+			// expected
+		}
+	}
+    
+    /**
+	 * @throws IOException
+	 * @tests java.util.Scanner#hasNextLong(int)
+	 */
+    public void test_hasNextLongI() throws IOException {
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextLong(10));
+        assertEquals(123, s.nextLong(10));
+        assertTrue(s.hasNextLong(10));
+        assertEquals(456, s.nextLong(10));
+        assertFalse(s.hasNextLong(10));
+        try {
+            s.nextLong(10);
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextLong(5));
+        assertEquals(38, s.nextLong(5));
+        assertFalse(s.hasNextLong(5));
+        try {
+            s.nextLong(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        assertFalse(s.hasNextLong(10));
+        try {
+            s.nextLong(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextShort(10));
+        try {
+            s.nextLong(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextLong(10));
+        assertEquals(23456, s.nextLong(10));
+        assertTrue(s.hasNextLong(10));
+        assertEquals(23456, s.nextLong(10));
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextLong(10));
+        try {
+            s.nextLong(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextLong(10));
+        assertEquals(23456, s.nextLong(10));
+        assertTrue(s.hasNextLong(10));
+        assertEquals(23456, s.nextLong(10));
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertTrue(s.hasNextLong(10));
+        assertEquals(102, s.nextLong(10));
+        assertFalse(s.hasNextLong(5));
+        try {
+            s.nextLong(5);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        assertTrue(s.hasNextLong(10));
+        assertEquals(162, s.nextLong(10));
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        assertFalse(s.hasNextLong(10));
+        try {
+            s.nextLong(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextLong(10));
+        assertEquals(23456, s.nextLong(10));
+        assertTrue(s.hasNextLong(10));
+        assertEquals(23456, s.nextLong(10));
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        assertFalse(s.hasNextLong(10));
+        try {
+            s.nextLong(10);
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertTrue(s.hasNextLong(10));
+        assertEquals(3456, s.nextLong(10));
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextLong(10));
+        assertEquals(3456, s.nextLong(10));
+
+        s = new Scanner("E34");
+        assertTrue(s.hasNextLong(16));
+        assertEquals(3636, s.nextLong(16));
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextLong(10));
+        assertEquals(12300, s.nextLong(10));
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextLong(10));
+        assertEquals(12300, s.nextLong(10));
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextLong(10));
+        assertEquals(12300, s.nextLong(10));
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextLong(10));
+        assertEquals(-123, s.nextLong(10));
+       
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextLong(10));
+        assertEquals(-123, s.nextLong(10));
+    }
+    
+    /**
+	 * @throws IOException
+	 * @tests java.util.Scanner#hasNextLong(int)
+	 */
+    public void test_hasNextLongI_cache() throws IOException {
+        //regression for HARMONY-2063
+    	s = new Scanner("123 456");
+		assertTrue(s.hasNextLong(16));
+		assertEquals(291, s.nextLong());
+		assertEquals(456, s.nextLong());
+
+		s = new Scanner("123 456");
+		assertTrue(s.hasNextLong(16));
+		assertTrue(s.hasNextLong(8));
+		assertEquals(83, s.nextLong());
+		assertEquals(456, s.nextLong());
+
+		s = new Scanner("-123 -456 -789");
+		assertTrue(s.hasNextLong(8));
+		assertEquals(-123, s.nextInt());
+		assertEquals(-456, s.nextLong());
+		assertTrue(s.hasNextShort(16));
+		assertEquals(-789, s.nextLong());
+		
+		s = new Scanner("123 456");
+		assertTrue(s.hasNextLong());
+		s.close();
+		try {
+			s.nextLong();
+			fail("Should throw IllegalStateException");
+		} catch (IllegalStateException e) {
+			// expected
+		}
+    }
+
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextLong()
+     */
+    public void test_hasNextLong() throws IOException {
+        s = new Scanner("123 456");
+        assertTrue(s.hasNextLong());
+        assertEquals(123, s.nextLong());
+        assertTrue(s.hasNextLong());
+        assertEquals(456, s.nextLong());
+        assertFalse(s.hasNextLong());
+        try {
+            s.nextLong();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        // If the radix is different from 10
+        s = new Scanner("123 456");
+        s.useRadix(5);
+        assertTrue(s.hasNextLong());
+        assertEquals(38, s.nextLong());
+        assertFalse(s.hasNextLong());
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // If the number is out of range
+        s = new Scanner("123456789123456789123456789123456789");
+        assertFalse(s.hasNextLong());
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextLong());
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.ENGLISH);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextLong());
+        assertEquals(23456, s.nextLong());
+        assertTrue(s.hasNextLong());
+        assertEquals(23456, s.nextLong());
+
+        /*
+         * ''' is used in many locales as group separator.
+         */
+        s = new Scanner("23'456 23'456");
+        s.useLocale(Locale.GERMANY);
+        assertFalse(s.hasNextLong());
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(new Locale("it", "CH"));
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextLong());
+        assertEquals(23456, s.nextLong());
+        assertTrue(s.hasNextLong());
+        assertEquals(23456, s.nextLong());
+
+        /*
+         * The input string has Arabic-Indic digits.
+         */
+        s = new Scanner("1\u06602 1\u06662");
+        assertEquals(102, s.nextLong());
+        s.useRadix(5);
+        assertFalse(s.hasNextLong());
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useRadix(10);
+        assertTrue(s.hasNextLong());
+        assertEquals(162, s.nextLong());
+
+        /*
+         * '.' is used in many locales as group separator. The input string
+         * has Arabic-Indic digits .
+         */
+        s = new Scanner("23.45\u0666 23.456");
+        s.useLocale(Locale.CHINESE);
+        assertFalse(s.hasNextLong());
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+        s.useLocale(Locale.GERMANY);
+        // If exception is thrown out, input will not be advanced.
+        assertTrue(s.hasNextLong());
+        assertEquals(23456, s.nextLong());
+        assertTrue(s.hasNextLong());
+        assertEquals(23456, s.nextLong());
+
+        // The input string starts with zero
+        s = new Scanner("03,456");
+        s.useLocale(Locale.ENGLISH);
+        assertFalse(s.hasNextLong());
+        try {
+            s.nextLong();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        s = new Scanner("03456");
+        assertTrue(s.hasNextLong());
+        assertEquals(3456, s.nextLong());
+
+        s = new Scanner("\u06603,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextLong());
+        assertEquals(3456, s.nextLong());
+
+        s = new Scanner("E34");
+        s.useRadix(16);
+        assertTrue(s.hasNextLong());
+        assertEquals(3636, s.nextLong());
+
+        /*
+         * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+         * respectively, but they are not differentiated.
+         */
+        s = new Scanner("12300");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextLong());
+        assertEquals(12300, s.nextLong());
+
+        s = new Scanner("123\u0966\u0966");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextLong());
+        assertEquals(12300, s.nextLong());
+        
+        s = new Scanner("123\u0e50\u0e50");
+        s.useLocale(Locale.CHINESE);
+        assertTrue(s.hasNextLong());
+        assertEquals(12300, s.nextLong());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("ar", "AE"));
+        assertTrue(s.hasNextLong());
+        assertEquals(-123, s.nextLong());
+
+        s = new Scanner("-123");
+        s.useLocale(new Locale("mk", "MK"));
+        assertTrue(s.hasNextLong());
+        assertEquals(-123, s.nextLong());
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextDouble()
+     */
+    public void test_hasNextDouble() throws IOException {
+        s = new Scanner("123 45\u0666. 123.4 .123 ");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextDouble());
+        assertEquals(123.0, s.nextDouble());
+        assertTrue(s.hasNextDouble());
+        assertEquals(456.0, s.nextDouble());
+        assertTrue(s.hasNextDouble());
+        assertEquals(123.4, s.nextDouble());
+        assertTrue(s.hasNextDouble());
+        assertEquals(0.123, s.nextDouble());
+        assertFalse(s.hasNextDouble());
+        try {
+            s.nextDouble();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextDouble());
+        assertEquals(123.4, s.nextDouble());
+        assertTrue(s.hasNextDouble());
+        assertEquals(-456.7, s.nextDouble());
+        assertTrue(s.hasNextDouble());
+        assertEquals(123456.789, s.nextDouble());
+        assertFalse(s.hasNextDouble());
+        try {
+            s.nextDouble();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // Scientific notation
+        s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextDouble());
+        assertEquals(1.234E12, s.nextDouble());
+        assertTrue(s.hasNextDouble());
+        assertEquals(-4.567E14, s.nextDouble());
+        assertTrue(s.hasNextDouble());
+        assertEquals(1.23456789E-5, s.nextDouble());
+
+        s = new Scanner("NaN Infinity -Infinity");
+        assertTrue(s.hasNextDouble());
+        assertEquals(Double.NaN, s.nextDouble());
+        assertTrue(s.hasNextDouble());
+        assertEquals(Double.POSITIVE_INFINITY, s.nextDouble());
+        assertTrue(s.hasNextDouble());
+        assertEquals(Double.NEGATIVE_INFINITY, s.nextDouble());
+
+        String str=String.valueOf(Double.MAX_VALUE*2);
+        s=new Scanner(str);
+        assertTrue(s.hasNextDouble());
+        assertEquals(Double.POSITIVE_INFINITY,s.nextDouble());
+        
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextDouble());
+        assertEquals(23456.0, s.nextDouble());
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextDouble());
+        assertEquals(23.456, s.nextDouble());
+
+        s = new Scanner("23.456 23.456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextDouble());
+        assertEquals(23.456, s.nextDouble());
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextDouble());
+        assertEquals(23456.0, s.nextDouble());
+
+        s = new Scanner("23,456.7 23.456,7");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextDouble());
+        assertEquals(23456.7, s.nextDouble());
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextDouble());
+        assertEquals(23456.7, s.nextDouble());
+
+        s = new Scanner("-123.4");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextDouble());
+        assertEquals(-123.4, s.nextDouble());
+        
+        s = new Scanner("+123.4 -456.7");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextDouble());
+        s.close();
+        try{
+        	s.nextDouble();
+        	fail("Should throw IllegalStateException");
+        }catch(IllegalStateException e){
+        	//expected
+        }
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#hasNextBigDecimal()
+     */
+    public void test_hasNextBigDecimal() throws IOException {
+        s = new Scanner("123 45\u0666. 123.4 .123 ");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("123"), s.nextBigDecimal());
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("456"), s.nextBigDecimal());
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("123.4"), s.nextBigDecimal());
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("0.123"), s.nextBigDecimal());
+        assertFalse(s.hasNextBigDecimal());
+        try {
+            s.nextBigDecimal();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("123.4"), s.nextBigDecimal());
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("-456.7"), s.nextBigDecimal());
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("123456.789"), s.nextBigDecimal());
+        assertFalse(s.hasNextBigDecimal());
+        try {
+            s.nextBigDecimal();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // Scientific notation
+        s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("1.234E12"), s.nextBigDecimal());
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("-4.567E14"), s.nextBigDecimal());
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("1.23456789E-5"), s.nextBigDecimal());
+
+        s = new Scanner("NaN");
+        assertFalse(s.hasNextBigDecimal());
+        try {
+            s.nextBigDecimal();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("23456"), s.nextBigDecimal());
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("23.456"), s.nextBigDecimal());
+
+        s = new Scanner("23.456 23.456");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("23.456"), s.nextBigDecimal());
+        s.useLocale(Locale.GERMANY);
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("23456"), s.nextBigDecimal());
+
+        s = new Scanner("23,456.7");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("23456.7"), s.nextBigDecimal());
+
+        s = new Scanner("-123.4");
+        s.useLocale(Locale.ENGLISH);
+        assertTrue(s.hasNextBigDecimal());
+        assertEquals(new BigDecimal("-123.4"), s.nextBigDecimal());
+    }
+    
+    private static class MockStringReader extends StringReader {
+
+        public MockStringReader(String param) {
+            super(param);
+        }
+
+        public int read(CharBuffer target) throws IOException {
+            target.append('t');
+            target.append('e');
+            target.append('s');
+            target.append('t');
+            throw new IOException();
+        }
+
+    }
+    
+    private static class MockStringReader2Read extends StringReader {
+        private int timesRead = 1;
+
+        public MockStringReader2Read(String param) {
+            super(param);
+        }
+
+        public int read(CharBuffer target) throws IOException {
+            if (timesRead == 1) {
+                target.append('1');
+                target.append('2');
+                target.append('3');
+                timesRead++;
+                return 3;
+            } else if (timesRead == 2) {
+                target.append('t');
+                timesRead++;
+                return 1;
+            } else {
+                throw new IOException();
+            }
+        }
+
+    }
+    
+    /**
+     * @tests java.util.Scanner#findWithinHorizon(Pattern, int)
+     */
+    public void test_findWithinHorizon_LPatternI(){
+
+        // This method searches through the input up to the specified search
+        // horizon(exclusive).
+        s = new Scanner("123test");
+        String result = s.findWithinHorizon(Pattern.compile("\\p{Lower}"), 5);
+        assertEquals("t", result);
+        MatchResult mresult = s.match();
+        assertEquals(3, mresult.start());
+        assertEquals(4, mresult.end());
+
+        s = new Scanner("12345test1234test next");
+        /*
+         * If the pattern is found the scanner advances past the input that
+         * matched and returns the string that matched the pattern.
+         */
+        result = s.findWithinHorizon(Pattern.compile("\\p{Digit}+"), 2);
+        assertEquals("12", result);
+        mresult = s.match();
+        assertEquals(0, mresult.start());
+        assertEquals(2, mresult.end());
+        // Position is now pointing at the bar. "12|345test1234test next"
+
+        result = s.findWithinHorizon(Pattern.compile("\\p{Digit}+"), 6);
+        assertEquals("345", result);
+
+        mresult = s.match();
+        assertEquals(2, mresult.start());
+        assertEquals(5, mresult.end());
+        // Position is now pointing at the bar. "12345|test1234test next"
+
+        // If no such pattern is detected then the null is returned and the
+        // scanner's position remains unchanged.
+        result = s.findWithinHorizon(Pattern.compile("\\p{Digit}+"), 3);
+        assertNull(result);
+
+        try {
+            s.match();
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+        assertEquals("345", mresult.group());
+        assertEquals(2, mresult.start());
+        assertEquals(5, mresult.end());
+        // Position is now still pointing at the bar. "12345|test1234test next"
+
+        // If horizon is 0, then the horizon is ignored and this method
+        // continues to search through the input looking for the specified
+        // pattern without bound.
+        result = s.findWithinHorizon(Pattern.compile("\\p{Digit}+"), 0);
+        mresult = s.match();
+        assertEquals(9, mresult.start());
+        assertEquals(13, mresult.end());
+        // Position is now pointing at the bar. "12345test1234|test next"
+
+        assertEquals("test", s.next());
+        mresult = s.match();
+        assertEquals(13, mresult.start());
+        assertEquals(17, mresult.end());
+
+        assertEquals("next", s.next());
+        mresult = s.match();
+        assertEquals(18, mresult.start());
+        assertEquals(22, mresult.end());
+
+        try {
+            s.findWithinHorizon((Pattern) null, -1);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            s.findWithinHorizon(Pattern.compile("\\p{Digit}+"), -1);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        s.close();
+        try {
+            s.findWithinHorizon((Pattern) null, -1);
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+
+        s = new Scanner("test");
+        result = s.findWithinHorizon(Pattern.compile("\\w+"), 10);
+        assertEquals("test", result);
+
+        s = new Scanner("aa\n\rb");
+        String patternStr = "^(a)$";
+        result = s.findWithinHorizon(Pattern.compile("a"), 5);
+        assertEquals("a", result);
+        mresult = s.match();
+        assertEquals(0, mresult.start());
+        assertEquals(1, mresult.end());
+
+        result = s.findWithinHorizon(Pattern.compile(patternStr,
+                Pattern.MULTILINE), 5);
+        assertNull(result);
+
+        try {
+            mresult = s.match();
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+
+        s = new Scanner("");
+        result = s.findWithinHorizon(Pattern.compile("^"), 0);
+        assertEquals("", result);
+        MatchResult matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(0, matchResult.end());
+
+        result = s.findWithinHorizon(Pattern.compile("$"), 0);
+        assertEquals("", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(0, matchResult.end());
+
+        s = new Scanner("1 fish 2 fish red fish blue fish");
+        result = s.findWithinHorizon(Pattern
+                .compile("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)"), 10);
+        assertNull(result);
+
+        try {
+            mresult = s.match();
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+        assertEquals(0, mresult.groupCount());
+
+        result = s.findWithinHorizon(Pattern
+                .compile("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)"), 100);
+        assertEquals("1 fish 2 fish red fish blue", result);
+        mresult = s.match();
+        assertEquals(4, mresult.groupCount());
+        assertEquals("1", mresult.group(1));
+        assertEquals("2", mresult.group(2));
+        assertEquals("red", mresult.group(3));
+        assertEquals("blue", mresult.group(4));
+
+        s = new Scanner("test");
+        s.close();
+        try {
+            s.findWithinHorizon(Pattern.compile("test"), 1);
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+
+        s = new Scanner("word1 WorD2  ");
+        s.close();
+        try {
+            s.findWithinHorizon(Pattern.compile("\\d+"), 10);
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+
+        s = new Scanner("word1 WorD2 wOrd3 ");
+        Pattern pattern = Pattern.compile("\\d+");
+        assertEquals("1", s.findWithinHorizon(pattern, 10));
+        assertEquals("WorD2", s.next());
+        assertEquals("3", s.findWithinHorizon(pattern, 15));
+
+        // Regression test
+        s = new Scanner(new MockStringReader("MockStringReader"));
+        pattern = Pattern.compile("test");
+        result = s.findWithinHorizon(pattern, 10);
+        assertEquals("test", result);
+
+        // Test the situation when input length is longer than buffer size.
+        StringBuilder stringBuilder = new StringBuilder();
+        for (int i = 0; i < 1026; i++) {
+            stringBuilder.append('a');
+        }
+        s = new Scanner(stringBuilder.toString());
+        pattern = Pattern.compile("\\p{Lower}+");
+        result = s.findWithinHorizon(pattern, 1026);
+        assertEquals(stringBuilder.toString(), result);
+
+        // Test the situation when input length is longer than buffer size and
+        // set horizon to buffer size.
+        stringBuilder = new StringBuilder();
+        for (int i = 0; i < 1026; i++) {
+            stringBuilder.append('a');
+        }
+        s = new Scanner(stringBuilder.toString());
+        pattern = Pattern.compile("\\p{Lower}+");
+        result = s.findWithinHorizon(pattern, 1022);
+        assertEquals(1022, result.length());
+        assertEquals(stringBuilder.subSequence(0, 1022), result);
+
+        // Test the situation, under which pattern is clipped by buffer.
+        stringBuilder = new StringBuilder();
+        for (int i = 0; i < 1022; i++) {
+            stringBuilder.append(' ');
+        }
+        stringBuilder.append("bbc");
+        assertEquals(1025, stringBuilder.length());
+        s = new Scanner(stringBuilder.toString());
+        pattern = Pattern.compile("bbc");
+        result = s.findWithinHorizon(pattern, 1025);
+        assertEquals(3, result.length());
+        assertEquals(stringBuilder.subSequence(1022, 1025), result);
+
+        stringBuilder = new StringBuilder();
+        for (int i = 0; i < 1026; i++) {
+            stringBuilder.append('a');
+        }
+        s = new Scanner(stringBuilder.toString());
+        pattern = Pattern.compile("\\p{Lower}+");
+        result = s.findWithinHorizon(pattern, 0);
+        assertEquals(stringBuilder.toString(), result);
+        
+        stringBuilder = new StringBuilder();
+        for (int i = 0; i < 10240; i++) {
+            stringBuilder.append('-');
+        }
+        stringBuilder.replace(0, 2, "aa");
+        s = new Scanner(stringBuilder.toString());
+        result = s.findWithinHorizon(Pattern.compile("aa"), 0);
+        assertEquals("aa", result);
+        
+        s = new Scanner("aaaa");
+        result = s.findWithinHorizon(Pattern.compile("a*"), 0);
+        assertEquals("aaaa", result);
+    }
+    
+    /**
+     * @tests java.util.Scanner#findInLine(Pattern)
+     */
+    public void test_findInLine_LPattern() {
+
+        Scanner s = new Scanner("");
+        try {
+            s.findInLine((Pattern) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+        String result = s.findInLine(Pattern.compile("^"));
+        assertEquals("", result);
+        MatchResult matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(0, matchResult.end());
+
+        result = s.findInLine(Pattern.compile("$"));
+        assertEquals("", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(0, matchResult.end());
+
+        /*
+         * When we use the operation of findInLine(Pattern), the match region
+         * should not span the line separator.
+         */
+        s = new Scanner("aa\nb.b");
+        result = s.findInLine(Pattern.compile("a\nb*"));
+        assertNull(result);
+
+        s = new Scanner("aa\nbb.b");
+        result = s.findInLine(Pattern.compile("\\."));
+        assertNull(result);
+
+        s = new Scanner("abcd1234test\n");
+        result = s.findInLine(Pattern.compile("\\p{Lower}+"));
+        assertEquals("abcd", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(4, matchResult.end());
+
+        result = s.findInLine(Pattern.compile("\\p{Digit}{5}"));
+        assertNull(result);
+        try {
+            matchResult = s.match();
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+        assertEquals(0, matchResult.start());
+        assertEquals(4, matchResult.end());
+
+        result = s.findInLine(Pattern.compile("\\p{Lower}+"));
+        assertEquals("test", result);
+        matchResult = s.match();
+        assertEquals(8, matchResult.start());
+        assertEquals(12, matchResult.end());
+
+        char[] chars = new char[2048];
+        Arrays.fill(chars, 'a');
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append(chars);
+        stringBuilder.append("1234");
+        s = new Scanner(stringBuilder.toString());
+        result = s.findInLine(Pattern.compile("\\p{Digit}+"));
+        assertEquals("1234", result);
+        matchResult = s.match();
+        assertEquals(2048, matchResult.start());
+        assertEquals(2052, matchResult.end());
+
+        s = new Scanner("test");
+        s.close();
+        try {
+            s.findInLine((Pattern) null);
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+
+        s = new Scanner("test1234\n1234 test");
+        result = s.findInLine(Pattern.compile("test"));
+        assertEquals("test", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(4, matchResult.end());
+
+        int number = s.nextInt();
+        assertEquals(1234, number);
+        matchResult = s.match();
+        assertEquals(4, matchResult.start());
+        assertEquals(8, matchResult.end());
+
+        result = s.next();
+        assertEquals("1234", result);
+        matchResult = s.match();
+        assertEquals(9, matchResult.start());
+        assertEquals(13, matchResult.end());
+
+        result = s.findInLine(Pattern.compile("test"));
+        assertEquals("test", result);
+        matchResult = s.match();
+        assertEquals(14, matchResult.start());
+        assertEquals(18, matchResult.end());
+        
+        s = new Scanner("test\u0085\ntest");
+        result = s.findInLine("est");
+        assertEquals("est", result);
+        result = s.findInLine("est");
+        assertEquals("est", result);
+        
+        s = new Scanner("test\ntest");
+        result = s.findInLine("est");
+        assertEquals("est", result);
+        result = s.findInLine("est");
+        assertEquals("est", result);
+
+        s = new Scanner("test\n123\ntest");
+        result = s.findInLine("est");
+        assertEquals("est", result);
+        result = s.findInLine("est");
+        // RI fails. It is a RI's bug.
+        assertNull(result);
+        
+        s = new Scanner( "   *\n");
+        result = s.findInLine(Pattern.compile( "^\\s*(?:\\*(?=[^/]))"));
+        assertEquals("   *", result);
+    }
+
+    /**
+     * @tests java.util.Scanner#findInLine(String)
+     */
+    public void test_findInLine_LString() {
+        s = new Scanner("test");
+        try {
+            s.findInLine((String) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        s.close();
+        try {
+            s.findInLine((String) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            s.findInLine("test");
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // exptected
+        }
+    }
+    
+    /**
+     * @tests java.util.Scanner#skip(Pattern)
+     */
+    public void test_skip_LPattern() {
+        s = new Scanner("test");
+        try {
+            s.skip((String) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        
+        // If pattern does not match, NoSuchElementException will be thrown out.
+        s = new Scanner("1234");
+        try {
+            s.skip(Pattern.compile("\\p{Lower}"));
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // expected
+        }
+        // Then, no matchResult will be thrown out.
+        try {
+            s.match();
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+
+        s.skip(Pattern.compile("\\p{Digit}"));
+        MatchResult matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1, matchResult.end());
+
+        s.skip(Pattern.compile("\\p{Digit}+"));
+        matchResult = s.match();
+        assertEquals(1, matchResult.start());
+        assertEquals(4, matchResult.end());
+
+        s.close();
+        try {
+            s.skip(Pattern.compile("test"));
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+
+        MockStringReader2Read reader = new MockStringReader2Read("test");
+        s = new Scanner(reader);
+        try {
+            s.skip(Pattern.compile("\\p{Digit}{4}"));
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // expected
+        }
+        try {
+            s.match();
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+        s.skip(Pattern.compile("\\p{Digit}{3}\\p{Lower}"));
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(4, matchResult.end());
+
+        s.close();
+        try {
+            s.skip((Pattern) null);
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+        
+        StringBuilder stringBuilder = new StringBuilder();
+        char [] chars = new char[1024];
+        Arrays.fill(chars, 'a');
+        stringBuilder.append(chars);
+        stringBuilder.append('3');
+        s = new Scanner(stringBuilder.toString());
+        s.skip(Pattern.compile("\\p{Lower}+\\p{Digit}"));
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1025, matchResult.end());
+        
+        // Large amount of input may be cached
+        chars = new char[102400];
+        Arrays.fill(chars, 'a');
+        stringBuilder = new StringBuilder();
+        stringBuilder.append(chars);
+        s = new Scanner(stringBuilder.toString());
+        s.skip(Pattern.compile(".*"));
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(102400, matchResult.end());
+        
+        // skip something without risking a NoSuchElementException
+        s.skip(Pattern.compile("[ \t]*"));
+        matchResult = s.match();
+        assertEquals(102400, matchResult.start());
+        assertEquals(102400, matchResult.end());
+    }
+
+    /**
+     * @tests java.util.Scanner#skip(String)
+     */
+    public void test_skip_LString() {
+        s = new Scanner("test");
+        try {
+            s.skip((String) null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextDouble()
+     */
+    public void test_nextDouble() throws IOException {
+        s = new Scanner("123 45\u0666. 123.4 .123 ");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(123.0, s.nextDouble());
+        assertEquals(456.0, s.nextDouble());
+        assertEquals(123.4, s.nextDouble());
+        assertEquals(0.123, s.nextDouble());
+        try {
+            s.nextDouble();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(123.4, s.nextDouble());
+        assertEquals(-456.7, s.nextDouble());
+        assertEquals(123456.789, s.nextDouble());
+        try {
+            s.nextDouble();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // Scientific notation
+        s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(1.234E12, s.nextDouble());
+        assertEquals(-4.567E14, s.nextDouble());
+        assertEquals(1.23456789E-5, s.nextDouble());
+
+        s = new Scanner("NaN Infinity -Infinity");
+        assertEquals(Double.NaN, s.nextDouble());
+        assertEquals(Double.POSITIVE_INFINITY, s.nextDouble());
+        assertEquals(Double.NEGATIVE_INFINITY, s.nextDouble());
+        
+        //The following test case fails on RI
+        s=new Scanner("\u221e");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(Double.POSITIVE_INFINITY, s.nextDouble());
+
+        String str=String.valueOf(Double.MAX_VALUE*2);
+        s=new Scanner(str);
+        assertEquals(Double.POSITIVE_INFINITY,s.nextDouble());
+        
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(23456.0, s.nextDouble());
+        s.useLocale(Locale.GERMANY);
+        assertEquals(23.456, s.nextDouble());
+
+        s = new Scanner("23.456 23.456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(23.456, s.nextDouble());
+        s.useLocale(Locale.GERMANY);
+        assertEquals(23456.0, s.nextDouble());
+
+        s = new Scanner("23,456.7 23.456,7");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(23456.7, s.nextDouble());
+        s.useLocale(Locale.GERMANY);
+        assertEquals(23456.7, s.nextDouble());
+
+        s = new Scanner("-123.4");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(-123.4, s.nextDouble());
+    }
+    
+    /**
+     * @throws IOException
+     * @tests java.util.Scanner#nextBigDecimal()
+     */
+    public void test_nextBigDecimal() throws IOException {
+        s = new Scanner("123 45\u0666. 123.4 .123 ");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(new BigDecimal("123"), s.nextBigDecimal());
+        assertEquals(new BigDecimal("456"), s.nextBigDecimal());
+        assertEquals(new BigDecimal("123.4"), s.nextBigDecimal());
+        assertEquals(new BigDecimal("0.123"), s.nextBigDecimal());
+        try {
+            s.nextBigDecimal();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // Expected
+        }
+
+        s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(new BigDecimal("123.4"), s.nextBigDecimal());
+        assertEquals(new BigDecimal("-456.7"), s.nextBigDecimal());
+        assertEquals(new BigDecimal("123456.789"), s.nextBigDecimal());
+        try {
+            s.nextBigDecimal();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        // Scientific notation
+        s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(new BigDecimal("1.234E12"), s.nextBigDecimal());
+        assertEquals(new BigDecimal("-4.567E14"), s.nextBigDecimal());
+        assertEquals(new BigDecimal("1.23456789E-5"), s.nextBigDecimal());
+
+        s = new Scanner("NaN");
+        try {
+            s.nextBigDecimal();
+            fail("Should throw InputMismatchException");
+        } catch (InputMismatchException e) {
+            // Expected
+        }
+
+        /*
+         * Different locale can only recognize corresponding locale sensitive
+         * string. ',' is used in many locales as group separator.
+         */
+        s = new Scanner("23,456 23,456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(new BigDecimal("23456"), s.nextBigDecimal());
+        s.useLocale(Locale.GERMANY);
+        assertEquals(new BigDecimal("23.456"), s.nextBigDecimal());
+
+        s = new Scanner("23.456 23.456");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(new BigDecimal("23.456"), s.nextBigDecimal());
+        s.useLocale(Locale.GERMANY);
+        assertEquals(new BigDecimal("23456"), s.nextBigDecimal());
+
+        s = new Scanner("23,456.7");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(new BigDecimal("23456.7"), s.nextBigDecimal());
+
+        s = new Scanner("-123.4");
+        s.useLocale(Locale.ENGLISH);
+        assertEquals(new BigDecimal("-123.4"), s.nextBigDecimal());
+    }
+
+    /**
+     * @tests java.util.Scanner#toString()
+     */
+    public void test_toString() {
+        s = new Scanner("test");
+        assertNotNull(s.toString());
+    }
+
+    /**
+     * @tests java.util.Scanner#nextLine()
+     */
+    public void test_nextLine() {
+        s = new Scanner("");
+        s.close();
+        try {
+            s.nextLine();
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+        
+        s = new Scanner("test\r\ntest");
+        String result = s.nextLine();
+        assertEquals("test", result);
+        MatchResult matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(6, matchResult.end());
+
+        s = new Scanner("\u0085");
+        result = s.nextLine();
+        assertEquals("", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1, matchResult.end());
+        
+        s = new Scanner("\u2028");
+        result = s.nextLine();
+        assertEquals("", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1, matchResult.end());
+        
+        s = new Scanner("\u2029");
+        result = s.nextLine();
+        assertEquals("", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1, matchResult.end());
+        
+        s = new Scanner("");
+        try {
+            result = s.nextLine();
+            fail("Should throw NoSuchElementException");
+        } catch (NoSuchElementException e) {
+            // expected
+        }
+        try {
+            s.match();
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+
+        s = new Scanner("Ttest");
+        result = s.nextLine();
+        assertEquals("Ttest", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(5, matchResult.end());
+
+        s = new Scanner("\r\n");
+        result = s.nextLine();
+        assertEquals("", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(2, matchResult.end());
+
+        char[] chars = new char[1024];
+        Arrays.fill(chars, 'a');
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append(chars);
+        chars = new char[] { '+', '-' };
+        stringBuilder.append(chars);
+        stringBuilder.append("\u2028");
+        s = new Scanner(stringBuilder.toString());
+        result = s.nextLine();
+
+        assertEquals(stringBuilder.toString().substring(0, 1026), result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1027, matchResult.end());
+
+        chars = new char[1023];
+        Arrays.fill(chars, 'a');
+        stringBuilder = new StringBuilder();
+        stringBuilder.append(chars);
+        stringBuilder.append("\r\n");
+        s = new Scanner(stringBuilder.toString());
+        result = s.nextLine();
+
+        assertEquals(stringBuilder.toString().substring(0, 1023), result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1025, matchResult.end());
+
+        s = new Scanner("  ");
+        result = s.nextLine();
+        assertEquals("  ", result);
+
+        s = new Scanner("test\n\n\n");
+        result = s.nextLine();
+        assertEquals("test", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(5, matchResult.end());
+        result = s.nextLine();
+        matchResult = s.match();
+        assertEquals(5, matchResult.start());
+        assertEquals(6, matchResult.end());
+
+        s = new Scanner("\n\n\n");
+        result = s.nextLine();
+        assertEquals("", result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1, matchResult.end());
+        result = s.nextLine();
+        matchResult = s.match();
+        assertEquals(1, matchResult.start());
+        assertEquals(2, matchResult.end());
+        
+        s = new Scanner("123 test\n   ");
+        int value = s.nextInt();
+        assertEquals(123, value);
+        
+        result = s.nextLine();
+        assertEquals(" test", result);
+        
+        s = new Scanner("test\n ");
+        result = s.nextLine();
+        assertEquals("test", result);
+
+        // Regression test for Harmony-4774
+        class CountReadable implements Readable {
+            int counter = 0;
+            public int read(CharBuffer charBuffer) throws IOException {
+                counter++;
+                charBuffer.append("hello\n");
+                return 6;
+            }
+        }
+        CountReadable cr = new CountReadable();
+        s = new Scanner(cr);
+        result = s.nextLine();
+        // We expect read() to be called only once, otherwise we see the problem
+        // when reading from System.in described in Harmony-4774
+        assertEquals(1, cr.counter);
+        assertEquals("hello", result);        
+    }
+    
+    /**
+     * @tests java.util.Scanner#hasNextLine()
+     */
+    public void test_hasNextLine() {
+        s = new Scanner("");
+        s.close();
+        try {
+            s.hasNextLine();
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            // expected
+        }
+        
+        s = new Scanner("test\r\ntest");
+        boolean result = s.hasNextLine();
+        assertTrue(result);
+        MatchResult matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(6, matchResult.end());
+
+        s = new Scanner("\u0085");
+        result = s.hasNextLine();
+        assertTrue(result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1, matchResult.end());
+        
+        s = new Scanner("\u2028");
+        result = s.hasNextLine();
+        assertTrue(result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1, matchResult.end());
+        
+        s = new Scanner("\u2029");
+        result = s.hasNextLine();
+        assertTrue(result);
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1, matchResult.end());
+        
+        s = new Scanner("test\n");
+        assertTrue(s.hasNextLine());
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(5, matchResult.end());
+
+        char[] chars = new char[2048];
+        Arrays.fill(chars, 'a');
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append(chars);
+        s = new Scanner(stringBuilder.toString());
+        result = s.hasNextLine();
+        assertTrue(result);
+
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(2048, matchResult.end());
+
+        s = new Scanner("\n\n\n");
+        assertTrue(s.hasNextLine());
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1, matchResult.end());
+
+        // The scanner will not advance any input.
+        assertTrue(s.hasNextLine());
+        matchResult = s.match();
+        assertEquals(0, matchResult.start());
+        assertEquals(1, matchResult.end());
+    }
+
+    public void test_hasNextLine_sequence() throws IOException {
+        final PipedInputStream pis = new PipedInputStream();
+        final PipedOutputStream pos = new PipedOutputStream();
+        final Scanner scanner = new Scanner(pis);
+        pis.connect(pos);
+        final List<String> result = new ArrayList<String>();
+        Thread thread = new Thread(new Runnable() {
+            public void run() {
+                while (scanner.hasNextLine()) {
+                    result.add(scanner.nextLine());
+                }
+            }
+        });
+        thread.start();
+        for (int index = 0; index < 5; index++) {
+            pos.write(("line" + index + "\n").getBytes());
+            pos.flush();
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+                // Ignored
+            }
+            assertEquals(index + 1, result.size());
+        }
+        pis.close();
+        pos.close();
+        try {
+            thread.join(1000);
+        } catch (InterruptedException e) {
+            // Ignored
+        }
+        assertFalse(scanner.hasNextLine());
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        server = new ServerSocket(0);
+        address = new InetSocketAddress("127.0.0.1", server.getLocalPort());
+
+        client = SocketChannel.open();
+        client.connect(address);
+        serverSocket = server.accept();
+
+        os = serverSocket.getOutputStream();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        try {
+            serverSocket.close();
+        } catch (Exception e) {
+
+        }
+        try {
+            client.close();
+        } catch (Exception e) {
+            // do nothing
+        }
+        try {
+            server.close();
+        } catch (Exception e) {
+            // do nothing
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/UUIDTest.java b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/UUIDTest.java
new file mode 100644
index 0000000..d8f4cc4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/UUIDTest.java
@@ -0,0 +1,457 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.harmony.luni.tests.java.util;
+
+import java.util.UUID;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+import junit.framework.TestCase;
+
+public class UUIDTest extends TestCase {
+
+    /**
+     * @see UUID#UUID(long, long)
+     */
+    public void test_ConstructorJJ() {
+        UUID uuid = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf6L);
+        assertEquals(2, uuid.variant());
+        assertEquals(1, uuid.version());
+        assertEquals(0x1d07decf81d4faeL, uuid.timestamp());
+        assertEquals(130742845922168750L, uuid.timestamp());
+        assertEquals(0x2765, uuid.clockSequence());
+        assertEquals(0xA0C91E6BF6L, uuid.node());
+    }
+
+    /**
+     * @see UUID#getLeastSignificantBits()
+     */
+    public void test_getLeastSignificantBits() {
+        UUID uuid = new UUID(0, 0);
+        assertEquals(0, uuid.getLeastSignificantBits());
+        uuid = new UUID(0, Long.MIN_VALUE);
+        assertEquals(Long.MIN_VALUE, uuid.getLeastSignificantBits());
+        uuid = new UUID(0, Long.MAX_VALUE);
+        assertEquals(Long.MAX_VALUE, uuid.getLeastSignificantBits());
+    }
+
+    /**
+     * @see UUID#getMostSignificantBits()
+     */
+    public void test_getMostSignificantBits() {
+        UUID uuid = new UUID(0, 0);
+        assertEquals(0, uuid.getMostSignificantBits());
+        uuid = new UUID(Long.MIN_VALUE, 0);
+        assertEquals(Long.MIN_VALUE, uuid.getMostSignificantBits());
+        uuid = new UUID(Long.MAX_VALUE, 0);
+        assertEquals(Long.MAX_VALUE, uuid.getMostSignificantBits());
+    }
+
+    /**
+     * @see UUID#version()
+     */
+    public void test_version() {
+        UUID uuid = new UUID(0, 0);
+        assertEquals(0, uuid.version());
+        uuid = new UUID(0x0000000000001000L, 0);
+        assertEquals(1, uuid.version());
+        uuid = new UUID(0x0000000000002000L, 0);
+        assertEquals(2, uuid.version());
+        uuid = new UUID(0x0000000000003000L, 0);
+        assertEquals(3, uuid.version());
+        uuid = new UUID(0x0000000000004000L, 0);
+        assertEquals(4, uuid.version());
+        uuid = new UUID(0x0000000000005000L, 0);
+        assertEquals(5, uuid.version());
+    }
+
+    /**
+     * @see UUID#variant()
+     */
+    public void test_variant() {
+        UUID uuid = new UUID(0, 0x0000000000000000L);
+        assertEquals(0, uuid.variant());
+        uuid = new UUID(0, 0x7000000000000000L);
+        assertEquals(0, uuid.variant());
+        uuid = new UUID(0, 0x3000000000000000L);
+        assertEquals(0, uuid.variant());
+        uuid = new UUID(0, 0x1000000000000000L);
+        assertEquals(0, uuid.variant());
+
+        uuid = new UUID(0, 0x8000000000000000L);
+        assertEquals(2, uuid.variant());
+        uuid = new UUID(0, 0xB000000000000000L);
+        assertEquals(2, uuid.variant());
+        uuid = new UUID(0, 0xA000000000000000L);
+        assertEquals(2, uuid.variant());
+        uuid = new UUID(0, 0x9000000000000000L);
+        assertEquals(2, uuid.variant());
+
+        uuid = new UUID(0, 0xC000000000000000L);
+        assertEquals(6, uuid.variant());
+        uuid = new UUID(0, 0xD000000000000000L);
+        assertEquals(6, uuid.variant());
+
+        uuid = new UUID(0, 0xE000000000000000L);
+        assertEquals(7, uuid.variant());
+        uuid = new UUID(0, 0xF000000000000000L);
+        assertEquals(7, uuid.variant());
+    }
+
+    /**
+     * @see UUID#timestamp()
+     */
+    public void test_timestamp() {
+        UUID uuid = new UUID(0x0000000000001000L, 0x8000000000000000L);
+        assertEquals(0x0, uuid.timestamp());
+
+        uuid = new UUID(0x7777777755551333L, 0x8000000000000000L);
+        assertEquals(0x333555577777777L, uuid.timestamp());
+
+        uuid = new UUID(0x0000000000000000L, 0x8000000000000000L);
+        try {
+            uuid.timestamp();
+            fail("No UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {}
+
+        uuid = new UUID(0x0000000000002000L, 0x8000000000000000L);
+        try {
+            uuid.timestamp();
+            fail("No UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {}
+    }
+
+    /**
+     * @see UUID#clockSequence()
+     */
+    public void test_clockSequence() {
+        UUID uuid = new UUID(0x0000000000001000L, 0x8000000000000000L);
+        assertEquals(0x0, uuid.clockSequence());
+
+        uuid = new UUID(0x0000000000001000L, 0x8FFF000000000000L);
+        assertEquals(0x0FFF, uuid.clockSequence());
+
+        uuid = new UUID(0x0000000000001000L, 0xBFFF000000000000L);
+        assertEquals(0x3FFF, uuid.clockSequence());
+
+        uuid = new UUID(0x0000000000000000L, 0x8000000000000000L);
+        try {
+            uuid.clockSequence();
+            fail("No UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {}
+
+        uuid = new UUID(0x0000000000002000L, 0x8000000000000000L);
+        try {
+            uuid.clockSequence();
+            fail("No UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {}
+    }
+
+    /**
+     * @see UUID#node()
+     */
+    public void test_node() {
+        UUID uuid = new UUID(0x0000000000001000L, 0x8000000000000000L);
+        assertEquals(0x0, uuid.node());
+
+        uuid = new UUID(0x0000000000001000L, 0x8000FFFFFFFFFFFFL);
+        assertEquals(0xFFFFFFFFFFFFL, uuid.node());
+
+        uuid = new UUID(0x0000000000000000L, 0x8000000000000000L);
+        try {
+            uuid.node();
+            fail("No UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {}
+
+        uuid = new UUID(0x0000000000002000L, 0x8000000000000000L);
+        try {
+            uuid.node();
+            fail("No UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {}
+    }
+
+    /**
+     * @see UUID#compareTo(UUID)
+     */
+    public void test_compareTo() {
+        UUID uuid1 = new UUID(0, 0);
+        assertEquals(0, uuid1.compareTo(uuid1));
+        UUID uuid2 = new UUID(1, 0);
+        assertEquals(-1, uuid1.compareTo(uuid2));
+        assertEquals(1, uuid2.compareTo(uuid1));
+
+        uuid2 = new UUID(0, 1);
+        assertEquals(-1, uuid1.compareTo(uuid2));
+        assertEquals(1, uuid2.compareTo(uuid1));
+    }
+
+    /**
+     * @see UUID#hashCode()
+     */
+    public void test_hashCode() {
+        UUID uuid = new UUID(0, 0);
+        assertEquals(0, uuid.hashCode());
+        uuid = new UUID(123, 123);
+        UUID uuidClone = new UUID(123, 123);
+        assertEquals(uuid.hashCode(), uuidClone.hashCode());
+    }
+
+    /**
+     * @see UUID#equals(Object)
+     */
+    public void test_equalsObject() {
+        UUID uuid1 = new UUID(0, 0);
+        assertEquals(uuid1, uuid1);
+        assertFalse(uuid1.equals(null));
+        assertFalse(uuid1.equals("NOT A UUID"));
+        UUID uuid2 = new UUID(0, 0);
+        assertEquals(uuid1, uuid2);
+        assertEquals(uuid2, uuid1);
+
+        uuid1 = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf6L);
+        uuid2 = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf6L);
+        assertEquals(uuid1, uuid2);
+        assertEquals(uuid2, uuid1);
+
+        uuid2 = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf7L);
+        assertFalse(uuid1.equals(uuid2));
+        assertFalse(uuid2.equals(uuid1));
+    }
+
+    /**
+     * @see UUID#toString()
+     */
+    public void test_toString() {
+        UUID uuid = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf6L);
+        String actual = uuid.toString();
+        assertEquals("f81d4fae-7dec-11d0-a765-00a0c91e6bf6", actual);
+
+        uuid = new UUID(0x0000000000001000L, 0x8000000000000000L);
+        actual = uuid.toString();
+        assertEquals("00000000-0000-1000-8000-000000000000", actual);
+    }
+
+    /**
+     * @tests serialization/deserialization.
+     */
+    public void testSerializationSelf() throws Exception {
+        SerializationTest.verifySelf(new UUID(0xf81d4fae7dec11d0L,
+                0xa76500a0c91e6bf6L));
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+        SerializationTest.verifyGolden(this, new UUID(0xf81d4fae7dec11d0L,
+                0xa76500a0c91e6bf6L));
+    }
+
+    /**
+     * @see UUID#randomUUID()
+     */
+    public void test_randomUUID() {
+        UUID uuid = UUID.randomUUID();
+        assertEquals(2, uuid.variant());
+        assertEquals(4, uuid.version());
+    }
+
+    /**
+     * @see UUID#nameUUIDFromBytes(byte[])
+     */
+    public void test_nameUUIDFromBytes() throws Exception {
+        byte[] name = { (byte) 0x6b, (byte) 0xa7, (byte) 0xb8, (byte) 0x11,
+                (byte) 0x9d, (byte) 0xad, (byte) 0x11, (byte) 0xd1,
+                (byte) 0x80, (byte) 0xb4, (byte) 0x00, (byte) 0xc0,
+                (byte) 0x4f, (byte) 0xd4, (byte) 0x30, (byte) 0xc8 };
+
+        UUID uuid = UUID.nameUUIDFromBytes(name);
+
+        assertEquals(2, uuid.variant());
+        assertEquals(3, uuid.version());
+
+        assertEquals(0xaff565bc2f771745L, uuid.getLeastSignificantBits());
+        assertEquals(0x14cdb9b4de013faaL, uuid.getMostSignificantBits());
+
+        uuid = UUID.nameUUIDFromBytes(new byte[0]);
+        assertEquals(2, uuid.variant());
+        assertEquals(3, uuid.version());
+
+        assertEquals(0xa9800998ecf8427eL, uuid.getLeastSignificantBits());
+        assertEquals(0xd41d8cd98f003204L, uuid.getMostSignificantBits());
+
+        try {
+            UUID.nameUUIDFromBytes(null);
+            fail("No NPE");
+        } catch (NullPointerException e) {}
+    }
+
+    /**
+     * @see UUID#fromString(String)
+     */
+    public void test_fromString() {
+        UUID actual = UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6");
+        UUID expected = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf6L);
+        assertEquals(expected, actual);
+
+        assertEquals(2, actual.variant());
+        assertEquals(1, actual.version());
+        assertEquals(130742845922168750L, actual.timestamp());
+        assertEquals(10085, actual.clockSequence());
+        assertEquals(690568981494L, actual.node());
+
+        actual = UUID.fromString("00000000-0000-1000-8000-000000000000");
+        expected = new UUID(0x0000000000001000L, 0x8000000000000000L);
+        assertEquals(expected, actual);
+
+        assertEquals(2, actual.variant());
+        assertEquals(1, actual.version());
+        assertEquals(0L, actual.timestamp());
+        assertEquals(0, actual.clockSequence());
+        assertEquals(0L, actual.node());
+
+        try {
+            UUID.fromString(null);
+            fail("No NPE");
+        } catch (NullPointerException e) {}
+
+        try {
+            UUID.fromString("");
+            fail("No IAE");
+        } catch (IllegalArgumentException e) {}
+
+        try {
+            UUID.fromString("f81d4fae_7dec-11d0-a765-00a0c91e6bf6");
+            fail("No IAE");
+        } catch (IllegalArgumentException e) {}
+
+        try {
+            UUID.fromString("f81d4fae-7dec_11d0-a765-00a0c91e6bf6");
+            fail("No IAE");
+        } catch (IllegalArgumentException e) {}
+
+        try {
+            UUID.fromString("f81d4fae-7dec-11d0_a765-00a0c91e6bf6");
+            fail("No IAE");
+        } catch (IllegalArgumentException e) {}
+
+        try {
+            UUID.fromString("f81d4fae-7dec-11d0-a765_00a0c91e6bf6");
+            fail("No IAE");
+        } catch (IllegalArgumentException e) {}
+    }
+
+	/**
+	 * @tests java.util.UUID#fromString(String)
+	 */
+	public void test_fromString_LString_Exception() {
+
+		UUID uuid = UUID.fromString("0-0-0-0-0");
+
+		try {
+			uuid = UUID.fromString("0-0-0-0-");
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+
+		try {
+			uuid = UUID.fromString("-0-0-0-0-0");
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+
+		try {
+			uuid = UUID.fromString("-0-0-0-0");
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+
+		try {
+			uuid = UUID.fromString("-0-0-0-");
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+
+		try {
+			uuid = UUID.fromString("0--0-0-0");
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+
+		try {
+			uuid = UUID.fromString("0-0-0-0-");
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+
+		try {
+			uuid = UUID.fromString("-1-0-0-0-0");
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+
+		uuid = UUID.fromString("123456789-0-0-0-0");
+		assertEquals(0x2345678900000000L, uuid.getMostSignificantBits());
+		assertEquals(0x0L, uuid.getLeastSignificantBits());
+
+		uuid = UUID.fromString("111123456789-0-0-0-0");
+		assertEquals(0x2345678900000000L, uuid.getMostSignificantBits());
+		assertEquals(0x0L, uuid.getLeastSignificantBits());
+
+		uuid = UUID.fromString("7fffffffffffffff-0-0-0-0");
+		assertEquals(0xffffffff00000000L, uuid.getMostSignificantBits());
+		assertEquals(0x0L, uuid.getLeastSignificantBits());
+
+		try {
+			uuid = UUID.fromString("8000000000000000-0-0-0-0");
+			fail("should throw NumberFormatException");
+		} catch (NumberFormatException e) {
+			// expected
+		}
+
+		uuid = UUID
+				.fromString("7fffffffffffffff-7fffffffffffffff-7fffffffffffffff-0-0");
+		assertEquals(0xffffffffffffffffL, uuid.getMostSignificantBits());
+		assertEquals(0x0L, uuid.getLeastSignificantBits());
+
+		uuid = UUID.fromString("0-0-0-7fffffffffffffff-7fffffffffffffff");
+		assertEquals(0x0L, uuid.getMostSignificantBits());
+		assertEquals(0xffffffffffffffffL, uuid.getLeastSignificantBits());
+
+		try {
+			uuid = UUID.fromString("0-0-0-8000000000000000-0");
+			fail("should throw NumberFormatException");
+		} catch (NumberFormatException e) {
+			// expected
+		}
+
+		try {
+			uuid = UUID.fromString("0-0-0-0-8000000000000000");
+			fail("should throw NumberFormatException");
+		} catch (NumberFormatException e) {
+			// expected
+		}
+	}
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/AbstractBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/AbstractBufferTest.java
new file mode 100644
index 0000000..eb48992
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/AbstractBufferTest.java
@@ -0,0 +1,306 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.InvalidMarkException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests a java.nio.Buffer instance.
+ */
+public class AbstractBufferTest extends TestCase {
+    
+    protected Buffer baseBuf;
+    
+    protected void setUp() throws Exception{
+    	super.setUp();
+    	baseBuf = ByteBuffer.allocate(10);
+    }
+    
+    protected void tearDown() throws Exception{
+    	super.tearDown();
+    }
+
+    public void testCapacity() {
+        assertTrue(0 <= baseBuf.position() && baseBuf.position() <= baseBuf.limit()
+                && baseBuf.limit() <= baseBuf.capacity());
+    }
+
+    public void testClear() {
+        // save state
+        int oldPosition = baseBuf.position();
+        int oldLimit = baseBuf.limit();
+
+        Buffer ret = baseBuf.clear();
+        assertSame(ret, baseBuf);
+        assertEquals(baseBuf.position(), 0);
+        assertEquals(baseBuf.limit(), baseBuf.capacity());
+        try {
+            baseBuf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$S
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // restore state
+        baseBuf.limit(oldLimit);
+        baseBuf.position(oldPosition);
+    }
+
+    public void testFlip() {
+        // save state
+        int oldPosition = baseBuf.position();
+        int oldLimit = baseBuf.limit();
+
+        Buffer ret = baseBuf.flip();
+        assertSame(ret, baseBuf);
+        assertEquals(baseBuf.position(), 0);
+        assertEquals(baseBuf.limit(), oldPosition);
+        try {
+            baseBuf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // restore state
+        baseBuf.limit(oldLimit);
+        baseBuf.position(oldPosition);
+    }
+
+    public void testHasRemaining() {
+        // save state
+        int oldPosition = baseBuf.position();
+        int oldLimit = baseBuf.limit();
+
+        assertEquals(baseBuf.hasRemaining(), baseBuf.position() < baseBuf.limit());
+        baseBuf.position(baseBuf.limit());
+        assertFalse(baseBuf.hasRemaining());
+
+        // restore state
+        baseBuf.limit(oldLimit);
+        baseBuf.position(oldPosition);
+    }
+
+    public void testIsReadOnly() {
+        baseBuf.isReadOnly();
+    }
+
+    /*
+     * Class under test for int limit()
+     */
+    public void testLimit() {
+        assertTrue(0 <= baseBuf.position() && baseBuf.position() <= baseBuf.limit()
+                && baseBuf.limit() <= baseBuf.capacity());
+    }
+
+    /*
+     * Class under test for Buffer limit(int)
+     */
+    public void testLimitint() {
+        // save state
+        int oldPosition = baseBuf.position();
+        int oldLimit = baseBuf.limit();
+
+        Buffer ret = baseBuf.limit(baseBuf.limit());
+        assertSame(ret, baseBuf);
+
+        baseBuf.mark();
+        baseBuf.limit(baseBuf.capacity());
+        assertEquals(baseBuf.limit(), baseBuf.capacity());
+        // position should not change
+        assertEquals(baseBuf.position(), oldPosition);
+        // mark should be valid
+        baseBuf.reset();
+
+        if (baseBuf.capacity() > 0) {
+            baseBuf.limit(baseBuf.capacity());
+            baseBuf.position(baseBuf.capacity());
+            baseBuf.mark();
+            baseBuf.limit(baseBuf.capacity() - 1);
+            // position should be the new limit
+            assertEquals(baseBuf.position(), baseBuf.limit());
+            // mark should be invalid
+            try {
+                baseBuf.reset();
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (InvalidMarkException e) {
+                // expected
+            }
+        }
+
+        try {
+            baseBuf.limit(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            baseBuf.limit(baseBuf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        // restore state
+        baseBuf.limit(oldLimit);
+        baseBuf.position(oldPosition);
+    }
+
+    public void testMark() {
+        // save state
+        int oldPosition = baseBuf.position();
+        int oldLimit = baseBuf.limit();
+
+        Buffer ret = baseBuf.mark();
+        assertSame(ret, baseBuf);
+
+        baseBuf.mark();
+        baseBuf.position(baseBuf.limit());
+        baseBuf.reset();
+        assertEquals(baseBuf.position(), oldPosition);
+
+        baseBuf.mark();
+        baseBuf.position(baseBuf.limit());
+        baseBuf.reset();
+        assertEquals(baseBuf.position(), oldPosition);
+
+        // restore state
+        baseBuf.limit(oldLimit);
+        baseBuf.position(oldPosition);
+    }
+
+    /*
+     * Class under test for int position()
+     */
+    public void testPosition() {
+        assertTrue(0 <= baseBuf.position() && baseBuf.position() <= baseBuf.limit()
+                && baseBuf.limit() <= baseBuf.capacity());
+    }
+
+    /*
+     * Class under test for Buffer position(int)
+     */
+    public void testPositionint() {
+        // save state
+        int oldPosition = baseBuf.position();
+        int oldLimit = baseBuf.limit();
+
+        try {
+            baseBuf.position(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            baseBuf.position(baseBuf.limit() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        baseBuf.mark();
+        baseBuf.position(baseBuf.position());
+        baseBuf.reset();
+        assertEquals(baseBuf.position(), oldPosition);
+
+        baseBuf.position(0);
+        assertEquals(baseBuf.position(), 0);
+        baseBuf.position(baseBuf.limit());
+        assertEquals(baseBuf.position(), baseBuf.limit());
+
+        if (baseBuf.capacity() > 0) {
+            baseBuf.limit(baseBuf.capacity());
+            baseBuf.position(baseBuf.limit());
+            baseBuf.mark();
+            baseBuf.position(baseBuf.limit() - 1);
+            assertEquals(baseBuf.position(), baseBuf.limit() - 1);
+            // mark should be invalid
+            try {
+                baseBuf.reset();
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (InvalidMarkException e) {
+                // expected
+            }
+        }
+
+        Buffer ret = baseBuf.position(0);
+        assertSame(ret, baseBuf);
+
+        // restore state
+        baseBuf.limit(oldLimit);
+        baseBuf.position(oldPosition);
+    }
+
+    public void testRemaining() {
+        assertEquals(baseBuf.remaining(), baseBuf.limit() - baseBuf.position());
+    }
+
+    public void testReset() {
+        // save state
+        int oldPosition = baseBuf.position();
+        int oldLimit = baseBuf.limit();
+
+        baseBuf.mark();
+        baseBuf.position(baseBuf.limit());
+        baseBuf.reset();
+        assertEquals(baseBuf.position(), oldPosition);
+
+        baseBuf.mark();
+        baseBuf.position(baseBuf.limit());
+        baseBuf.reset();
+        assertEquals(baseBuf.position(), oldPosition);
+
+        Buffer ret = baseBuf.reset();
+        assertSame(ret, baseBuf);
+
+        baseBuf.clear();
+        try {
+            baseBuf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // restore state
+        baseBuf.limit(oldLimit);
+        baseBuf.position(oldPosition);
+    }
+
+    public void testRewind() {
+        // save state
+        int oldPosition = baseBuf.position();
+        int oldLimit = baseBuf.limit();
+
+        Buffer ret = baseBuf.rewind();
+        assertEquals(baseBuf.position(), 0);
+        assertSame(ret, baseBuf);
+        try {
+            baseBuf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // restore state
+        baseBuf.limit(oldLimit);
+        baseBuf.position(oldPosition);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java
new file mode 100644
index 0000000..39059fe
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java
@@ -0,0 +1,52 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+public class BufferOverflowExceptionTest extends TestCase {
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new BufferOverflowException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new BufferOverflowException());
+    }
+    
+    /**
+     *@tests {@link java.nio.BufferOverflowException#BufferOverflowException()}
+     */
+    public void test_Constructor() {
+        BufferOverflowException exception = new BufferOverflowException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getLocalizedMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java
new file mode 100644
index 0000000..a056ebf
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java
@@ -0,0 +1,55 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferUnderflowException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for BufferUnderflowException
+ */
+public class BufferUnderflowExceptionTest extends TestCase {
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new BufferUnderflowException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new BufferUnderflowException());
+    }
+    
+    /**
+     *@tests {@link java.nio.BufferUnderflowException#BufferUnderflowException()}
+     */
+    public void test_Constructor() {
+        BufferUnderflowException exception = new BufferUnderflowException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getLocalizedMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteBufferTest.java
new file mode 100644
index 0000000..d6d8681
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteBufferTest.java
@@ -0,0 +1,2177 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.InvalidMarkException;
+import java.nio.LongBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.nio.ShortBuffer;
+import java.util.Arrays;
+
+/**
+ * Tests java.nio.ByteBuffer
+ * 
+ */
+public class ByteBufferTest extends AbstractBufferTest {
+    protected static final int SMALL_TEST_LENGTH = 5;
+    protected static final int BUFFER_LENGTH = 250;
+    
+    protected ByteBuffer buf;
+
+    protected void setUp() throws Exception {
+        buf = ByteBuffer.allocate(10);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testArray() {
+        if (buf.hasArray()) {
+            byte array[] = buf.array();
+            assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+            loadTestData1(array, buf.arrayOffset(), buf.capacity());
+            assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+            loadTestData2(array, buf.arrayOffset(), buf.capacity());
+            assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+            loadTestData1(buf);
+            assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+            loadTestData2(buf);
+            assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+        } else {
+            if (buf.isReadOnly()) {
+                try {
+                    buf.array();
+                    fail("Should throw Exception"); //$NON-NLS-1$
+                } catch (UnsupportedOperationException e) {
+                    // expected
+                    // Note:can not tell when to throw 
+                    // UnsupportedOperationException
+                    // or ReadOnlyBufferException, so catch all.
+                }
+            } else {
+                try {
+                    buf.array();
+                    fail("Should throw Exception"); //$NON-NLS-1$
+                } catch (UnsupportedOperationException e) {
+                    // expected
+                }
+            }
+        }
+    }
+
+    public void testArrayOffset() {
+        if (buf.hasArray()) {
+            byte array[] = buf.array();
+            assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+            loadTestData1(array, buf.arrayOffset(), buf.capacity());
+            assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+            loadTestData2(array, buf.arrayOffset(), buf.capacity());
+            assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+            loadTestData1(buf);
+            assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+            loadTestData2(buf);
+            assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+        } else {
+            if (buf.isReadOnly()) {
+                try {
+                    buf.arrayOffset();
+                    fail("Should throw Exception"); //$NON-NLS-1$
+                } catch (UnsupportedOperationException e) {
+                    // expected
+                    // Note:can not tell when to throw 
+                    // UnsupportedOperationException
+                    // or ReadOnlyBufferException, so catch all.
+                }
+            } else {
+                try {
+                    buf.arrayOffset();
+                    fail("Should throw Exception"); //$NON-NLS-1$
+                } catch (UnsupportedOperationException e) {
+                    // expected
+                }
+            }
+        }
+    }
+
+    public void testAsReadOnlyBuffer() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // readonly's contents should be the same as buf
+        ByteBuffer readonly = buf.asReadOnlyBuffer();
+        assertNotSame(buf, readonly);
+        assertTrue(readonly.isReadOnly());
+        assertEquals(buf.position(), readonly.position());
+        assertEquals(buf.limit(), readonly.limit());
+        assertEquals(buf.isDirect(), readonly.isDirect());
+        assertEquals(buf.order(), readonly.order());
+        assertContentEquals(buf, readonly);
+
+        // readonly's position, mark, and limit should be independent to buf
+        readonly.reset();
+        assertEquals(readonly.position(), 0);
+        readonly.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+    }
+
+    public void testCompact() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.compact();
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        // case: buffer is full
+        buf.clear();
+        buf.mark();
+        loadTestData1(buf);
+        ByteBuffer ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), buf.capacity());
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, (byte) 0, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: buffer is empty
+        buf.position(0);
+        buf.limit(0);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 0);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, (byte) 0, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: normal
+        assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+        buf.position(1);
+        buf.limit(SMALL_TEST_LENGTH);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 4);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, (byte) 1, 4);
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+    }
+
+    public void testCompareTo() {
+        // compare to self
+        assertEquals(0, buf.compareTo(buf));
+
+        // normal cases
+        if (!buf.isReadOnly()) {
+            assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+            buf.clear();
+            ByteBuffer other = ByteBuffer.allocate(buf.capacity());
+            loadTestData1(buf);
+            loadTestData1(other);
+            assertEquals(0, buf.compareTo(other));
+            assertEquals(0, other.compareTo(buf));
+            buf.position(1);
+            assertTrue(buf.compareTo(other) > 0);
+            assertTrue(other.compareTo(buf) < 0);
+            other.position(2);
+            assertTrue(buf.compareTo(other) < 0);
+            assertTrue(other.compareTo(buf) > 0);
+            buf.position(2);
+            other.limit(SMALL_TEST_LENGTH);
+            assertTrue(buf.compareTo(other) > 0);
+            assertTrue(other.compareTo(buf) < 0);
+        }
+        
+        assertTrue(ByteBuffer.wrap(new byte[21]).compareTo(ByteBuffer.allocateDirect(21)) == 0);
+    }
+
+    public void testDuplicate() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // duplicate's contents should be the same as buf
+        ByteBuffer duplicate = buf.duplicate();
+        assertNotSame(buf, duplicate);
+        assertEquals(buf.position(), duplicate.position());
+        assertEquals(buf.limit(), duplicate.limit());
+        assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+        assertEquals(buf.isDirect(), duplicate.isDirect());
+        assertEquals(buf.order(), duplicate.order());
+        assertContentEquals(buf, duplicate);
+
+        // duplicate's position, mark, and limit should be independent to buf
+        duplicate.reset();
+        assertEquals(duplicate.position(), 0);
+        duplicate.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+
+        // duplicate share the same content with buf
+        if (!duplicate.isReadOnly()) {
+            loadTestData1(buf);
+            assertContentEquals(buf, duplicate);
+            loadTestData2(duplicate);
+            assertContentEquals(buf, duplicate);
+        }
+    }
+
+    public void testEquals() {
+        // equal to self
+        assertTrue(buf.equals(buf));
+        ByteBuffer readonly = buf.asReadOnlyBuffer();
+        assertTrue(buf.equals(readonly));
+        ByteBuffer duplicate = buf.duplicate();
+        assertTrue(buf.equals(duplicate));
+
+        // always false, if type mismatch
+        assertFalse(buf.equals(Boolean.TRUE));
+
+        assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+
+        buf.limit(buf.capacity()).position(0);
+        readonly.limit(readonly.capacity()).position(1);
+        assertFalse(buf.equals(readonly));
+
+        buf.limit(buf.capacity() - 1).position(0);
+        duplicate.limit(duplicate.capacity()).position(0);
+        assertFalse(buf.equals(duplicate));
+    }
+
+    /*
+     * Class under test for byte get()
+     */
+    public void testGet() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i));
+        }
+        try {
+            buf.get();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.ByteBuffer get(byte[])
+     */
+    public void testGetbyteArray() {
+        byte array[] = new byte[1];
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            ByteBuffer ret = buf.get(array);
+            assertEquals(array[0], buf.get(i));
+            assertSame(ret, buf);
+        }
+        try {
+            buf.get(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+        try {
+            buf.get((byte[])null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.ByteBuffer get(byte[], int, int)
+     */
+    public void testGetbyteArrayintint() {
+        buf.clear();
+        byte array[] = new byte[buf.capacity()];
+
+        try {
+            buf.get(new byte[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.get(array, array.length, 0);
+        try {
+            buf.get(array, array.length + 1, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, 2, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get((byte[])null, -1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+
+        buf.clear();
+        ByteBuffer ret = buf.get(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for byte get(int)
+     */
+    public void testGetint() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i));
+        }
+        try {
+            buf.get(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(buf.limit());
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testHasArray() {
+        if (buf.hasArray()) {
+            assertNotNull(buf.array());
+        } else {
+            if (buf.isReadOnly()) {
+                try {
+                    buf.array();
+                    fail("Should throw Exception"); //$NON-NLS-1$
+                } catch (UnsupportedOperationException e) {
+                    // expected
+                    // Note:can not tell when to throw 
+                    // UnsupportedOperationException
+                    // or ReadOnlyBufferException, so catch all.
+                }
+            } else {
+                try {
+                    buf.array();
+                    fail("Should throw Exception"); //$NON-NLS-1$
+                } catch (UnsupportedOperationException e) {
+                    // expected
+                }
+            }
+        }
+    }
+
+    public void testHashCode() {
+        buf.clear();
+        loadTestData1(buf);
+        ByteBuffer readonly = buf.asReadOnlyBuffer();
+        ByteBuffer duplicate = buf.duplicate();
+        assertTrue(buf.hashCode() == readonly.hashCode());
+        assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+        duplicate.position(buf.capacity()/2);
+        assertTrue(buf.hashCode()!= duplicate.hashCode());
+    }
+    
+    //for the testHashCode() method of readonly subclasses
+    protected void readOnlyHashCode() {
+        //create a new buffer initiated with some data 
+        ByteBuffer buf = ByteBuffer.allocate(BUFFER_LENGTH);
+        loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        buf.clear();
+        ByteBuffer readonly = buf.asReadOnlyBuffer();
+        ByteBuffer duplicate = buf.duplicate();
+        assertEquals(buf.hashCode(),readonly.hashCode());
+        duplicate.position(buf.capacity()/2);
+        assertTrue(buf.hashCode()!= duplicate.hashCode());
+    }
+
+    public void testIsDirect() {
+        buf.isDirect();
+    }
+
+    public void testOrder() {
+        // BIG_ENDIAN is the default byte order
+        assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+        assertEquals(ByteOrder.LITTLE_ENDIAN, buf.order());
+        
+        buf.order(ByteOrder.BIG_ENDIAN);
+        assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+
+        // Regression test for HARMONY-798
+        buf.order((ByteOrder)null);
+        assertEquals(ByteOrder.LITTLE_ENDIAN, buf.order());
+        
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    /*
+     * Class under test for java.nio.ByteBuffer put(byte)
+     */
+    public void testPutbyte() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.clear();
+                buf.put((byte) 0);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            ByteBuffer ret = buf.put((byte) i);
+            assertEquals(buf.get(i), (byte) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put((byte) 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.ByteBuffer put(byte[])
+     */
+    public void testPutbyteArray() {
+        byte array[] = new byte[1];
+        if (buf.isReadOnly()) {
+            try {
+                buf.put(array);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            array[0] = (byte) i;
+            ByteBuffer ret = buf.put(array);
+            assertEquals(buf.get(i), (byte) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        try {
+            buf.put((byte[])null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.ByteBuffer put(byte[], int, int)
+     */
+    public void testPutbyteArrayintint() {
+        buf.clear();
+        byte array[] = new byte[buf.capacity()];
+        if (buf.isReadOnly()) {
+            try {
+                buf.put(array, 0, array.length);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        try {
+            buf.put(new byte[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, array.length + 1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.put(array, array.length, 0);
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            buf.put(array, 2, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put((byte[])null, 2, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        
+        assertEquals(buf.position(), 0);
+
+        loadTestData2(array, 0, array.length);
+        ByteBuffer ret = buf.put(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.ByteBuffer put(java.nio.ByteBuffer)
+     */
+    public void testPutByteBuffer() {
+        ByteBuffer other = ByteBuffer.allocate(buf.capacity());
+        if (buf.isReadOnly()) {
+            try {
+                buf.clear();
+                buf.put(other);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            try {
+                buf.clear();
+                buf.put((ByteBuffer)null);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        try {
+            buf.put(buf);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            buf.put(ByteBuffer.allocate(buf.capacity() + 1));
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        
+        try {
+            buf.put((ByteBuffer)null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        loadTestData2(other);
+        other.clear();
+        buf.clear();
+        ByteBuffer ret = buf.put(other);
+        assertEquals(other.position(), other.capacity());
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(other, buf);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.ByteBuffer put(int, byte)
+     */
+    public void testPutintbyte() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.put(0, (byte) 0);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), 0);
+            ByteBuffer ret = buf.put(i, (byte) i);
+            assertEquals(buf.get(i), (byte) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(-1, (byte) 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(buf.limit(), (byte) 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testSlice() {
+        assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+        buf.position(1);
+        buf.limit(buf.capacity() - 1);
+
+        ByteBuffer slice = buf.slice();
+        assertEquals(buf.isReadOnly(), slice.isReadOnly());
+        assertEquals(buf.isDirect(), slice.isDirect());
+        assertEquals(buf.order(), slice.order());
+        assertEquals(slice.position(), 0);
+        assertEquals(slice.limit(), buf.remaining());
+        assertEquals(slice.capacity(), buf.remaining());
+        try {
+            slice.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // slice share the same content with buf
+        if (!slice.isReadOnly()) {
+            loadTestData1(slice);
+            assertContentLikeTestData1(buf, 1, (byte) 0, slice.capacity());
+            buf.put(2, (byte) 100);
+            assertEquals(slice.get(1), 100);
+        }
+    }
+
+    public void testToString() {
+        String str = buf.toString();
+        assertTrue(str.indexOf("Byte") >= 0 || str.indexOf("byte") >= 0);
+        assertTrue(str.indexOf("" + buf.position()) >= 0);
+        assertTrue(str.indexOf("" + buf.limit()) >= 0);
+        assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+    }
+
+    public void testAsCharBuffer() {
+        CharBuffer charBuffer;
+        byte bytes[] = new byte[2];
+        char value;
+
+        // test BIG_ENDIAN char buffer, read
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+        charBuffer = buf.asCharBuffer();
+        assertSame(ByteOrder.BIG_ENDIAN, charBuffer.order());
+        while (charBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = charBuffer.get();
+            assertEquals(bytes2char(bytes, buf.order()), value);
+        }
+
+        // test LITTLE_ENDIAN char buffer, read
+        buf.clear();
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+        charBuffer = buf.asCharBuffer();
+        assertSame(ByteOrder.LITTLE_ENDIAN, charBuffer.order());
+        while (charBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = charBuffer.get();
+            assertEquals(bytes2char(bytes, buf.order()), value);
+        }
+
+        if (!buf.isReadOnly()) {
+            // test BIG_ENDIAN char buffer, write
+            buf.clear();
+            buf.order(ByteOrder.BIG_ENDIAN);
+            charBuffer = buf.asCharBuffer();
+            assertSame(ByteOrder.BIG_ENDIAN, charBuffer.order());
+            while (charBuffer.remaining() > 0) {
+                value = (char) charBuffer.remaining();
+                charBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, char2bytes(value, buf.order())));
+            }
+
+            // test LITTLE_ENDIAN char buffer, write
+            buf.clear();
+            buf.order(ByteOrder.LITTLE_ENDIAN);
+            charBuffer = buf.asCharBuffer();
+            assertSame(ByteOrder.LITTLE_ENDIAN, charBuffer.order());
+            while (charBuffer.remaining() > 0) {
+                value = (char) charBuffer.remaining();
+                charBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, char2bytes(value, buf.order())));
+            }
+        }
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testAsDoubleBuffer() {
+        DoubleBuffer doubleBuffer;
+        byte bytes[] = new byte[8];
+        double value;
+
+        // test BIG_ENDIAN double buffer, read
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+        doubleBuffer = buf.asDoubleBuffer();
+        assertSame(ByteOrder.BIG_ENDIAN, doubleBuffer.order());
+        while (doubleBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = doubleBuffer.get();
+            if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+                    .isNaN(value))) {
+                assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+            }
+        }
+
+        // test LITTLE_ENDIAN double buffer, read
+        buf.clear();
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+        doubleBuffer = buf.asDoubleBuffer();
+        assertSame(ByteOrder.LITTLE_ENDIAN, doubleBuffer.order());
+        while (doubleBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = doubleBuffer.get();
+            if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+                    .isNaN(value))) {
+                assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+            }
+        }
+
+        if (!buf.isReadOnly()) {
+            // test BIG_ENDIAN double buffer, write
+            buf.clear();
+            buf.order(ByteOrder.BIG_ENDIAN);
+            doubleBuffer = buf.asDoubleBuffer();
+            assertSame(ByteOrder.BIG_ENDIAN, doubleBuffer.order());
+            while (doubleBuffer.remaining() > 0) {
+                value = (double) doubleBuffer.remaining();
+                doubleBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, double2bytes(value, buf.order())));
+            }
+
+            // test LITTLE_ENDIAN double buffer, write
+            buf.clear();
+            buf.order(ByteOrder.LITTLE_ENDIAN);
+            doubleBuffer = buf.asDoubleBuffer();
+            assertSame(ByteOrder.LITTLE_ENDIAN, doubleBuffer.order());
+            while (doubleBuffer.remaining() > 0) {
+                value = (double) doubleBuffer.remaining();
+                doubleBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, double2bytes(value, buf.order())));
+            }
+        }
+
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testAsFloatBuffer() {
+        FloatBuffer floatBuffer;
+        byte bytes[] = new byte[4];
+        float value;
+
+        // test BIG_ENDIAN float buffer, read
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+        floatBuffer = buf.asFloatBuffer();
+        assertSame(ByteOrder.BIG_ENDIAN, floatBuffer.order());
+        while (floatBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = floatBuffer.get();
+            if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+                    .isNaN(value))) {
+                assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+            }
+        }
+
+        // test LITTLE_ENDIAN float buffer, read
+        buf.clear();
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+        floatBuffer = buf.asFloatBuffer();
+        assertSame(ByteOrder.LITTLE_ENDIAN, floatBuffer.order());
+        while (floatBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = floatBuffer.get();
+            if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+                    .isNaN(value))) {
+                assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+            }
+        }
+
+        if (!buf.isReadOnly()) {
+            // test BIG_ENDIAN float buffer, write
+            buf.clear();
+            buf.order(ByteOrder.BIG_ENDIAN);
+            floatBuffer = buf.asFloatBuffer();
+            assertSame(ByteOrder.BIG_ENDIAN, floatBuffer.order());
+            while (floatBuffer.remaining() > 0) {
+                value = (float) floatBuffer.remaining();
+                floatBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, float2bytes(value, buf.order())));
+            }
+
+            // test LITTLE_ENDIAN float buffer, write
+            buf.clear();
+            buf.order(ByteOrder.LITTLE_ENDIAN);
+            floatBuffer = buf.asFloatBuffer();
+            assertSame(ByteOrder.LITTLE_ENDIAN, floatBuffer.order());
+            while (floatBuffer.remaining() > 0) {
+                value = (float) floatBuffer.remaining();
+                floatBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, float2bytes(value, buf.order())));
+            }
+        }
+
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testAsIntBuffer() {
+        IntBuffer intBuffer;
+        byte bytes[] = new byte[4];
+        int value;
+
+        // test BIG_ENDIAN int buffer, read
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+        intBuffer = buf.asIntBuffer();
+        assertSame(ByteOrder.BIG_ENDIAN, intBuffer.order());
+        while (intBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = intBuffer.get();
+            assertEquals(bytes2int(bytes, buf.order()), value);
+        }
+
+        // test LITTLE_ENDIAN int buffer, read
+        buf.clear();
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+        intBuffer = buf.asIntBuffer();
+        assertSame(ByteOrder.LITTLE_ENDIAN, intBuffer.order());
+        while (intBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = intBuffer.get();
+            assertEquals(bytes2int(bytes, buf.order()), value);
+        }
+
+        if (!buf.isReadOnly()) {
+            // test BIG_ENDIAN int buffer, write
+            buf.clear();
+            buf.order(ByteOrder.BIG_ENDIAN);
+            intBuffer = buf.asIntBuffer();
+            assertSame(ByteOrder.BIG_ENDIAN, intBuffer.order());
+            while (intBuffer.remaining() > 0) {
+                value = (int) intBuffer.remaining();
+                intBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, int2bytes(value, buf.order())));
+            }
+
+            // test LITTLE_ENDIAN int buffer, write
+            buf.clear();
+            buf.order(ByteOrder.LITTLE_ENDIAN);
+            intBuffer = buf.asIntBuffer();
+            assertSame(ByteOrder.LITTLE_ENDIAN, intBuffer.order());
+            while (intBuffer.remaining() > 0) {
+                value = (int) intBuffer.remaining();
+                intBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, int2bytes(value, buf.order())));
+            }
+        }
+
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testAsLongBuffer() {
+        LongBuffer longBuffer;
+        byte bytes[] = new byte[8];
+        long value;
+
+        // test BIG_ENDIAN long buffer, read
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+        longBuffer = buf.asLongBuffer();
+        assertSame(ByteOrder.BIG_ENDIAN, longBuffer.order());
+        while (longBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = longBuffer.get();
+            assertEquals(bytes2long(bytes, buf.order()), value);
+        }
+
+        // test LITTLE_ENDIAN long buffer, read
+        buf.clear();
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+        longBuffer = buf.asLongBuffer();
+        assertSame(ByteOrder.LITTLE_ENDIAN, longBuffer.order());
+        while (longBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = longBuffer.get();
+            assertEquals(bytes2long(bytes, buf.order()), value);
+        }
+
+        if (!buf.isReadOnly()) {
+            // test BIG_ENDIAN long buffer, write
+            buf.clear();
+            buf.order(ByteOrder.BIG_ENDIAN);
+            longBuffer = buf.asLongBuffer();
+            assertSame(ByteOrder.BIG_ENDIAN, longBuffer.order());
+            while (longBuffer.remaining() > 0) {
+                value = (long) longBuffer.remaining();
+                longBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, long2bytes(value, buf.order())));
+            }
+
+            // test LITTLE_ENDIAN long buffer, write
+            buf.clear();
+            buf.order(ByteOrder.LITTLE_ENDIAN);
+            longBuffer = buf.asLongBuffer();
+            assertSame(ByteOrder.LITTLE_ENDIAN, longBuffer.order());
+            while (longBuffer.remaining() > 0) {
+                value = (long) longBuffer.remaining();
+                longBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, long2bytes(value, buf.order())));
+            }
+        }
+
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testAsShortBuffer() {
+        ShortBuffer shortBuffer;
+        byte bytes[] = new byte[2];
+        short value;
+
+        // test BIG_ENDIAN short buffer, read
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+        shortBuffer = buf.asShortBuffer();
+        assertSame(ByteOrder.BIG_ENDIAN, shortBuffer.order());
+        while (shortBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = shortBuffer.get();
+            assertEquals(bytes2short(bytes, buf.order()), value);
+        }
+
+        // test LITTLE_ENDIAN short buffer, read
+        buf.clear();
+        buf.order(ByteOrder.LITTLE_ENDIAN);
+        shortBuffer = buf.asShortBuffer();
+        assertSame(ByteOrder.LITTLE_ENDIAN, shortBuffer.order());
+        while (shortBuffer.remaining() > 0) {
+            buf.get(bytes);
+            value = shortBuffer.get();
+            assertEquals(bytes2short(bytes, buf.order()), value);
+        }
+
+        if (!buf.isReadOnly()) {
+            // test BIG_ENDIAN short buffer, write
+            buf.clear();
+            buf.order(ByteOrder.BIG_ENDIAN);
+            shortBuffer = buf.asShortBuffer();
+            assertSame(ByteOrder.BIG_ENDIAN, shortBuffer.order());
+            while (shortBuffer.remaining() > 0) {
+                value = (short) shortBuffer.remaining();
+                shortBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, short2bytes(value, buf.order())));
+            }
+
+            // test LITTLE_ENDIAN short buffer, write
+            buf.clear();
+            buf.order(ByteOrder.LITTLE_ENDIAN);
+            shortBuffer = buf.asShortBuffer();
+            assertSame(ByteOrder.LITTLE_ENDIAN, shortBuffer.order());
+            while (shortBuffer.remaining() > 0) {
+                value = (short) shortBuffer.remaining();
+                shortBuffer.put(value);
+                buf.get(bytes);
+                assertTrue(Arrays.equals(bytes, short2bytes(value, buf.order())));
+            }
+        }
+
+        buf.clear();
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetChar() {
+        int nbytes = 2;
+        byte bytes[] = new byte[nbytes];
+        char value;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            assertEquals(i * nbytes, buf.position());
+            buf.mark();
+            buf.get(bytes);
+            buf.reset();
+            value = buf.getChar();
+            assertEquals(bytes2char(bytes, buf.order()), value);
+        }
+
+        try {
+            buf.getChar();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetCharint() {
+        int nbytes = 2;
+        byte bytes[] = new byte[nbytes];
+        char value;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            buf.position(i);
+            value = buf.getChar(i);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            assertEquals(bytes2char(bytes, buf.order()), value);
+        }
+
+        try {
+            buf.getChar(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.getChar(buf.limit() - nbytes + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testPutChar() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.clear();
+                buf.putChar((char) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 2;
+        byte bytes[] = new byte[nbytes];
+        char value = 0;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (char) i;
+            buf.mark();
+            buf.putChar(value);
+            assertEquals((i + 1) * nbytes, buf.position());
+            buf.reset();
+            buf.get(bytes);
+            assertTrue(Arrays.equals(char2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putChar(value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testPutCharint() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.putChar(0, (char) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 2;
+        byte bytes[] = new byte[nbytes];
+        char value = 0;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (char) i;
+            buf.position(i);
+            buf.putChar(i, value);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            assertTrue(Arrays.equals(char2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putChar(-1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.putChar(buf.limit() - nbytes + 1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+
+        try {
+        	ByteBuffer.allocateDirect(16).putChar(Integer.MAX_VALUE, 'h');
+        } catch (IndexOutOfBoundsException e) {
+        	//expected 
+        }
+    }
+
+    public void testGetDouble() {
+        int nbytes = 8;
+        byte bytes[] = new byte[nbytes];
+        double value;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            assertEquals(i * nbytes, buf.position());
+            buf.mark();
+            buf.get(bytes);
+            buf.reset();
+            value = buf.getDouble();
+            if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+                    .isNaN(value))) {
+                assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+            }
+        }
+
+        try {
+            buf.getDouble();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetDoubleint() {
+        int nbytes = 8;
+        byte bytes[] = new byte[nbytes];
+        double value;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            buf.position(i);
+            value = buf.getDouble(i);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+                    .isNaN(value))) {
+                assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+            }
+        }
+
+        try {
+            buf.getDouble(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.getDouble(buf.limit() - nbytes + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+
+        try {
+        	ByteBuffer.allocateDirect(16).getDouble(Integer.MAX_VALUE);
+        } catch (IndexOutOfBoundsException e) {
+        	//expected 
+        }
+    }
+
+    public void testPutDouble() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.clear();
+                buf.putDouble((double) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 8;
+        byte bytes[] = new byte[nbytes];
+        double value = 0;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (double) i;
+            buf.mark();
+            buf.putDouble(value);
+            assertEquals((i + 1) * nbytes, buf.position());
+            buf.reset();
+            buf.get(bytes);
+            assertTrue(Arrays.equals(double2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putDouble(value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testPutDoubleint() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.putDouble(0, (double) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 8;
+        byte bytes[] = new byte[nbytes];
+        double value = 0;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (double) i;
+            buf.position(i);
+            buf.putDouble(i, value);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            assertTrue(Arrays.equals(double2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putDouble(-1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.putDouble(buf.limit() - nbytes + 1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetFloat() {
+        int nbytes = 4;
+        byte bytes[] = new byte[nbytes];
+        float value;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            assertEquals(i * nbytes, buf.position());
+            buf.mark();
+            buf.get(bytes);
+            buf.reset();
+            value = buf.getFloat();
+            if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+                    .isNaN(value))) {
+                assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+            }
+        }
+
+        try {
+            buf.getFloat();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetFloatint() {
+        int nbytes = 4;
+        byte bytes[] = new byte[nbytes];
+        float value;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            buf.position(i);
+            value = buf.getFloat(i);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+                    .isNaN(value))) {
+                assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+            }
+        }
+
+        try {
+            buf.getFloat(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.getFloat(buf.limit() - nbytes + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testPutFloat() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.clear();
+                buf.putFloat((float) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 4;
+        byte bytes[] = new byte[nbytes];
+        float value = 0;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (float) i;
+            buf.mark();
+            buf.putFloat(value);
+            assertEquals((i + 1) * nbytes, buf.position());
+            buf.reset();
+            buf.get(bytes);
+            assertTrue(Arrays.equals(float2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putFloat(value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testPutFloatint() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.putFloat(0, (float) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 4;
+        byte bytes[] = new byte[nbytes];
+        float value = 0;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (float) i;
+            buf.position(i);
+            buf.putFloat(i, value);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            assertTrue(Arrays.equals(float2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putFloat(-1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.putFloat(buf.limit() - nbytes + 1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetInt() {
+        int nbytes = 4;
+        byte bytes[] = new byte[nbytes];
+        int value;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            assertEquals(i * nbytes, buf.position());
+            buf.mark();
+            buf.get(bytes);
+            buf.reset();
+            value = buf.getInt();
+            assertEquals(bytes2int(bytes, buf.order()), value);
+        }
+
+        try {
+            buf.getInt();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetIntint() {
+        int nbytes = 4;
+        byte bytes[] = new byte[nbytes];
+        int value;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            buf.position(i);
+            value = buf.getInt(i);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            assertEquals(bytes2int(bytes, buf.order()), value);
+        }
+
+        try {
+            buf.getInt(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.getInt(buf.limit() - nbytes + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+        try {
+        	ByteBuffer.allocateDirect(16).getInt(Integer.MAX_VALUE);
+        } catch (IndexOutOfBoundsException e) {
+        	//expected 
+        }
+    }
+
+    public void testPutInt() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.clear();
+                buf.putInt((int) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 4;
+        byte bytes[] = new byte[nbytes];
+        int value = 0;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (int) i;
+            buf.mark();
+            buf.putInt(value);
+            assertEquals((i + 1) * nbytes, buf.position());
+            buf.reset();
+            buf.get(bytes);
+            assertTrue(Arrays.equals(int2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putInt(value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testPutIntint() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.putInt(0, (int) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 4;
+        byte bytes[] = new byte[nbytes];
+        int value = 0;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (int) i;
+            buf.position(i);
+            buf.putInt(i, value);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            assertTrue(Arrays.equals(int2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putInt(-1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.putInt(buf.limit() - nbytes + 1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetLong() {
+        int nbytes = 8;
+        byte bytes[] = new byte[nbytes];
+        long value;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            assertEquals(i * nbytes, buf.position());
+            buf.mark();
+            buf.get(bytes);
+            buf.reset();
+            value = buf.getLong();
+            assertEquals(bytes2long(bytes, buf.order()), value);
+        }
+
+        try {
+            buf.getLong();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetLongint() {
+        int nbytes = 8;
+        byte bytes[] = new byte[nbytes];
+        long value;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            buf.position(i);
+            value = buf.getLong(i);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            assertEquals(bytes2long(bytes, buf.order()), value);
+        }
+
+        try {
+            buf.getLong(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.getLong(buf.limit() - nbytes + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testPutLong() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.clear();
+                buf.putLong((long) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 8;
+        byte bytes[] = new byte[nbytes];
+        long value = 0;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (long) i;
+            buf.mark();
+            buf.putLong(value);
+            assertEquals((i + 1) * nbytes, buf.position());
+            buf.reset();
+            buf.get(bytes);
+            assertTrue(Arrays.equals(long2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putLong(value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testPutLongint() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.putLong(0, (long) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 8;
+        byte bytes[] = new byte[nbytes];
+        long value = 0;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (long) i;
+            buf.position(i);
+            buf.putLong(i, value);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            assertTrue(Arrays.equals(long2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putLong(-1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.putLong(buf.limit() - nbytes + 1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetShort() {
+        int nbytes = 2;
+        byte bytes[] = new byte[nbytes];
+        short value;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            assertEquals(i * nbytes, buf.position());
+            buf.mark();
+            buf.get(bytes);
+            buf.reset();
+            value = buf.getShort();
+            assertEquals(bytes2short(bytes, buf.order()), value);
+        }
+
+        try {
+            buf.getShort();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testGetShortint() {
+        int nbytes = 2;
+        byte bytes[] = new byte[nbytes];
+        short value;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            buf.position(i);
+            value = buf.getShort(i);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            assertEquals(bytes2short(bytes, buf.order()), value);
+        }
+
+        try {
+            buf.getShort(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.getShort(buf.limit() - nbytes + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testPutShort() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.clear();
+                buf.putShort((short) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 2;
+        byte bytes[] = new byte[nbytes];
+        short value = 0;
+        buf.clear();
+        for (int i = 0; buf.remaining() >= nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (short) i;
+            buf.mark();
+            buf.putShort(value);
+            assertEquals((i + 1) * nbytes, buf.position());
+            buf.reset();
+            buf.get(bytes);
+            assertTrue(Arrays.equals(short2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putShort(value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+
+    public void testPutShortint() {
+        if (buf.isReadOnly()) {
+            try {
+                buf.putShort(0, (short) 1);
+                fail("Should throw Exception"); //$NON-NLS-1$
+            } catch (ReadOnlyBufferException e) {
+                // expected
+            }
+            return;
+        }
+
+        int nbytes = 2;
+        byte bytes[] = new byte[nbytes];
+        short value = 0;
+        buf.clear();
+        for (int i = 0; i <= buf.limit() - nbytes; i++) {
+            buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+                    : ByteOrder.LITTLE_ENDIAN);
+            value = (short) i;
+            buf.position(i);
+            buf.putShort(i, value);
+            assertEquals(i, buf.position());
+            buf.get(bytes);
+            assertTrue(Arrays.equals(short2bytes(value, buf.order()), bytes));
+        }
+
+        try {
+            buf.putShort(-1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.putShort(buf.limit() - nbytes + 1, value);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        buf.order(ByteOrder.BIG_ENDIAN);
+    }
+    
+    /**
+     * @tests java.nio.ByteBuffer.wrap(byte[],int,int)
+     */
+    public void testWrappedByteBuffer_null_array() {
+        // Regression for HARMONY-264
+        byte array[] = null;
+        try {
+            ByteBuffer.wrap(array, -1, 0);
+            fail("Should throw NPE"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+        }
+        try {
+            ByteBuffer.wrap(new byte[10], Integer.MAX_VALUE, 2);
+            fail("Should throw IndexOutOfBoundsException"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+        }
+    }
+
+    private void loadTestData1(byte array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (byte) i;
+        }
+    }
+
+    private void loadTestData2(byte array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (byte) (length - i);
+        }
+    }
+
+    private void loadTestData1(ByteBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (byte) i);
+        }
+    }
+
+    private void loadTestData2(ByteBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (byte) (buf.capacity() - i));
+        }
+    }
+
+    private void assertContentEquals(ByteBuffer buf, byte array[],
+            int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(i), array[offset + i]);
+        }
+    }
+
+    private void assertContentEquals(ByteBuffer buf, ByteBuffer other) {
+        assertEquals(buf.capacity(), other.capacity());
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.get(i), other.get(i));
+        }
+    }
+
+    private void assertContentLikeTestData1(ByteBuffer buf,
+            int startIndex, byte startValue, int length) {
+        byte value = startValue;
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(startIndex + i), value);
+            value = (byte) (value + 1);
+        }
+    }
+
+    private int bytes2int(byte bytes[], ByteOrder order) {
+        int nbytes = 4, bigHead, step;
+        if (order == ByteOrder.BIG_ENDIAN) {
+            bigHead = 0;
+            step = 1;
+        } else {
+            bigHead = nbytes - 1;
+            step = -1;
+        }
+        int result = 0;
+        int p = bigHead;
+        for (int i = 0; i < nbytes; i++) {
+            result = result << 8;
+            result = result | (bytes[p] & 0xff);
+            p += step;
+        }
+        return result;
+    }
+
+    private long bytes2long(byte bytes[], ByteOrder order) {
+        int nbytes = 8, bigHead, step;
+        if (order == ByteOrder.BIG_ENDIAN) {
+            bigHead = 0;
+            step = 1;
+        } else {
+            bigHead = nbytes - 1;
+            step = -1;
+        }
+        long result = 0;
+        int p = bigHead;
+        for (int i = 0; i < nbytes; i++) {
+            result = result << 8;
+            result = result | (bytes[p] & 0xff);
+            p += step;
+        }
+        return result;
+    }
+
+    private short bytes2short(byte bytes[], ByteOrder order) {
+        int nbytes = 2, bigHead, step;
+        if (order == ByteOrder.BIG_ENDIAN) {
+            bigHead = 0;
+            step = 1;
+        } else {
+            bigHead = nbytes - 1;
+            step = -1;
+        }
+        short result = 0;
+        int p = bigHead;
+        for (int i = 0; i < nbytes; i++) {
+            result = (short) (result << 8);
+            result = (short) (result | (bytes[p] & 0xff));
+            p += step;
+        }
+        return result;
+    }
+
+    private char bytes2char(byte bytes[], ByteOrder order) {
+        return (char) bytes2short(bytes, order);
+    }
+
+    private float bytes2float(byte bytes[], ByteOrder order) {
+        return Float.intBitsToFloat(bytes2int(bytes, order));
+    }
+
+    private double bytes2double(byte bytes[], ByteOrder order) {
+        return Double.longBitsToDouble(bytes2long(bytes, order));
+    }
+
+    private byte[] int2bytes(int value, ByteOrder order) {
+        int nbytes = 4, smallHead, step;
+        if (order == ByteOrder.BIG_ENDIAN) {
+            smallHead = nbytes - 1;
+            step = -1;
+        } else {
+            smallHead = 0;
+            step = 1;
+        }
+        byte bytes[] = new byte[nbytes];
+        int p = smallHead;
+        for (int i = 0; i < nbytes; i++) {
+            bytes[p] = (byte) (value & 0xff);
+            value = value >> 8;
+            p += step;
+        }
+        return bytes;
+    }
+
+    private byte[] long2bytes(long value, ByteOrder order) {
+        int nbytes = 8, smallHead, step;
+        if (order == ByteOrder.BIG_ENDIAN) {
+            smallHead = nbytes - 1;
+            step = -1;
+        } else {
+            smallHead = 0;
+            step = 1;
+        }
+        byte bytes[] = new byte[nbytes];
+        int p = smallHead;
+        for (int i = 0; i < nbytes; i++) {
+            bytes[p] = (byte) (value & 0xff);
+            value = value >> 8;
+            p += step;
+        }
+        return bytes;
+    }
+
+    private byte[] short2bytes(short value, ByteOrder order) {
+        int nbytes = 2, smallHead, step;
+        if (order == ByteOrder.BIG_ENDIAN) {
+            smallHead = nbytes - 1;
+            step = -1;
+        } else {
+            smallHead = 0;
+            step = 1;
+        }
+        byte bytes[] = new byte[nbytes];
+        int p = smallHead;
+        for (int i = 0; i < nbytes; i++) {
+            bytes[p] = (byte) (value & 0xff);
+            value = (short) (value >> 8);
+            p += step;
+        }
+        return bytes;
+    }
+
+    private byte[] char2bytes(char value, ByteOrder order) {
+        return short2bytes((short) value, order);
+    }
+
+    private byte[] float2bytes(float value, ByteOrder order) {
+        return int2bytes(Float.floatToRawIntBits(value), order);
+    }
+
+    private byte[] double2bytes(double value, ByteOrder order) {
+        return long2bytes(Double.doubleToRawLongBits(value), order);
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteOrderTest.java
similarity index 60%
copy from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
copy to harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteOrderTest.java
index 7fe2d7f..8f41904 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteOrderTest.java
@@ -15,19 +15,26 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.xnet.provider.jsse;
+package org.apache.harmony.nio.tests.java.nio;
 
-import java.io.IOException;
+import java.nio.ByteOrder;
+
+import junit.framework.TestCase;
 
 /**
- * This exception indicates that data could not be read from the stream because the underlying input
- * stream reached its end.
+ * Test java.nio.ByteOrder
+ * 
  */
-public class EndOfBufferException extends IOException {
+public class ByteOrderTest extends TestCase {
 
-    private static final long serialVersionUID = 1838636631255369519L;
+    public void testToString() {
+        assertEquals(ByteOrder.BIG_ENDIAN.toString(), "BIG_ENDIAN");
+        assertEquals(ByteOrder.LITTLE_ENDIAN.toString(), "LITTLE_ENDIAN");
+    }
 
-    public EndOfBufferException() {
+    public void testNativeOrder() {
+        ByteOrder o = ByteOrder.nativeOrder();
+        assertTrue(o == ByteOrder.BIG_ENDIAN || o == ByteOrder.LITTLE_ENDIAN);
     }
 
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java
new file mode 100644
index 0000000..8a7c5f3
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java
@@ -0,0 +1,1081 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.io.IOException;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.InvalidMarkException;
+import java.nio.ReadOnlyBufferException;
+
+/**
+ * Tests java.nio.CharBuffer
+ * 
+ */
+public class CharBufferTest extends AbstractBufferTest {
+	protected static final int SMALL_TEST_LENGTH = 5;
+
+	protected static final int BUFFER_LENGTH = 20;
+
+	protected CharBuffer buf;
+	
+	private static char[] chars = "123456789a".toCharArray();
+	
+	protected void setUp() throws Exception{
+		char[] charscopy = new char[chars.length];
+		System.arraycopy(chars, 0, charscopy, 0, chars.length);
+		buf = CharBuffer.wrap(charscopy);
+		baseBuf = buf;
+	}
+	
+	protected void tearDown() throws Exception{
+		buf = null;
+		baseBuf = null;
+	}
+
+	public void testArray() {
+		char array[] = buf.array();
+		assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+		loadTestData1(array, buf.arrayOffset(), buf.capacity());
+		assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+		loadTestData2(array, buf.arrayOffset(), buf.capacity());
+		assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+		loadTestData1(buf);
+		assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+		loadTestData2(buf);
+		assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+	}
+
+	public void testArrayOffset() {
+		char array[] = buf.array();
+		assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+		loadTestData1(array, buf.arrayOffset(), buf.capacity());
+		assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+		loadTestData2(array, buf.arrayOffset(), buf.capacity());
+		assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+		loadTestData1(buf);
+		assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+		loadTestData2(buf);
+		assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+	}
+
+	public void testAsReadOnlyBuffer() {
+		buf.clear();
+		buf.mark();
+		buf.position(buf.limit());
+
+		// readonly's contents should be the same as buf
+		CharBuffer readonly = buf.asReadOnlyBuffer();
+		assertNotSame(buf, readonly);
+		assertTrue(readonly.isReadOnly());
+		assertEquals(buf.position(), readonly.position());
+		assertEquals(buf.limit(), readonly.limit());
+		assertEquals(buf.isDirect(), readonly.isDirect());
+		assertEquals(buf.order(), readonly.order());
+		assertEquals(buf.capacity(), readonly.capacity());
+		assertContentEquals(buf, readonly);
+
+		// readonly's position, mark, and limit should be independent to buf
+		readonly.reset();
+		assertEquals(readonly.position(), 0);
+		readonly.clear();
+		assertEquals(buf.position(), buf.limit());
+		buf.reset();
+		assertEquals(buf.position(), 0);
+
+		buf.clear();
+		int originalPosition = (buf.position() + buf.limit()) / 2;
+		buf.position(originalPosition);
+		buf.mark();
+		buf.position(buf.limit());
+
+		// readonly's contents should be the same as buf
+		readonly = buf.asReadOnlyBuffer();
+		assertNotSame(buf, readonly);
+		assertTrue(readonly.isReadOnly());
+		assertEquals(buf.position(), readonly.position());
+		assertEquals(buf.limit(), readonly.limit());
+		assertEquals(buf.isDirect(), readonly.isDirect());
+		assertEquals(buf.order(), readonly.order());
+		assertEquals(buf.capacity(), readonly.capacity());
+		assertContentEquals(buf, readonly);
+
+		// readonly's position, mark, and limit should be independent to buf
+		readonly.reset();
+		assertEquals(readonly.position(), originalPosition);
+		readonly.clear();
+		assertEquals(buf.position(), buf.limit());
+		buf.reset();
+		assertEquals(buf.position(), originalPosition);
+	}
+
+	public void testCompact() {
+		// case: buffer is full
+		buf.clear();
+		buf.mark();
+		loadTestData1(buf);
+		CharBuffer ret = buf.compact();
+		assertSame(ret, buf);
+		assertEquals(buf.position(), buf.capacity());
+		assertEquals(buf.limit(), buf.capacity());
+		assertContentLikeTestData1(buf, 0, (char) 0, buf.capacity());
+		try {
+			buf.reset();
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (InvalidMarkException e) {
+			// expected
+		}
+
+		// case: buffer is empty
+		buf.position(0);
+		buf.limit(0);
+		buf.mark();
+		ret = buf.compact();
+		assertSame(ret, buf);
+		assertEquals(buf.position(), 0);
+		assertEquals(buf.limit(), buf.capacity());
+		assertContentLikeTestData1(buf, 0, (char) 0, buf.capacity());
+		try {
+			buf.reset();
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (InvalidMarkException e) {
+			// expected
+		}
+
+		// case: normal
+		assertTrue(buf.capacity() > 5);
+		buf.position(1);
+		buf.limit(5);
+		buf.mark();
+		ret = buf.compact();
+		assertSame(ret, buf);
+		assertEquals(buf.position(), 4);
+		assertEquals(buf.limit(), buf.capacity());
+		assertContentLikeTestData1(buf, 0, (char) 1, 4);
+		try {
+			buf.reset();
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (InvalidMarkException e) {
+			// expected
+		}
+	}
+
+	public void testCompareTo() {
+		// compare to self
+		assertEquals(0, buf.compareTo(buf));
+
+		assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+		buf.clear();
+		CharBuffer other = CharBuffer.allocate(buf.capacity());
+		other.put(buf);
+		other.clear();
+		buf.clear();
+		assertEquals(0, buf.compareTo(other));
+		assertEquals(0, other.compareTo(buf));
+		buf.position(1);
+		assertTrue(buf.compareTo(other) > 0);
+		assertTrue(other.compareTo(buf) < 0);
+		other.position(2);
+		assertTrue(buf.compareTo(other) < 0);
+		assertTrue(other.compareTo(buf) > 0);
+		buf.position(2);
+		assertTrue(buf.compareTo(other) == 0);
+		assertTrue(other.compareTo(buf) == 0);
+		other.limit(SMALL_TEST_LENGTH);
+		assertTrue(buf.compareTo(other) > 0);
+		assertTrue(other.compareTo(buf) < 0);
+	}
+
+	public void testDuplicate() {
+		// mark the position 0
+		buf.clear();
+		buf.mark();
+		buf.position(buf.limit());
+
+		// duplicate's contents should be the same as buf
+		CharBuffer duplicate = buf.duplicate();
+		assertNotSame(buf, duplicate);
+		assertEquals(buf.position(), duplicate.position());
+		assertEquals(buf.limit(), duplicate.limit());
+		assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+		assertEquals(buf.isDirect(), duplicate.isDirect());
+		assertEquals(buf.order(), duplicate.order());
+		assertEquals(buf.capacity(), duplicate.capacity());
+		assertContentEquals(buf, duplicate);
+
+		// duplicate's position, mark, and limit should be independent to
+		// buf
+		duplicate.reset();
+		assertEquals(duplicate.position(), 0);
+		duplicate.clear();
+		assertEquals(buf.position(), buf.limit());
+		buf.reset();
+		assertEquals(buf.position(), 0);
+
+		// mark another position
+		buf.clear();
+		int originalPosition = (buf.position() + buf.limit()) / 2;
+		buf.position(originalPosition);
+		buf.mark();
+		buf.position(buf.limit());
+
+		// duplicate's contents should be the same as buf
+		duplicate = buf.duplicate();
+		assertNotSame(buf, duplicate);
+		assertEquals(buf.position(), duplicate.position());
+		assertEquals(buf.limit(), duplicate.limit());
+		assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+		assertEquals(buf.isDirect(), duplicate.isDirect());
+		assertEquals(buf.order(), duplicate.order());
+		assertEquals(buf.capacity(), duplicate.capacity());
+		assertContentEquals(buf, duplicate);
+
+		// duplicate's position, mark, and limit should be independent to
+		// buf
+		duplicate.reset();
+		assertEquals(duplicate.position(), originalPosition);
+		duplicate.clear();
+		assertEquals(buf.position(), buf.limit());
+		buf.reset();
+		assertEquals(buf.position(), originalPosition);
+
+		// duplicate share the same content with buf
+		if (!duplicate.isReadOnly()) {
+			loadTestData1(buf);
+			assertContentEquals(buf, duplicate);
+			loadTestData2(duplicate);
+			assertContentEquals(buf, duplicate);
+		}
+	}
+
+	public void testEquals() {
+		// equal to self
+		assertTrue(buf.equals(buf));
+		CharBuffer readonly = buf.asReadOnlyBuffer();
+		assertTrue(buf.equals(readonly));
+		CharBuffer duplicate = buf.duplicate();
+		assertTrue(buf.equals(duplicate));
+
+		// always false, if type mismatch
+		assertFalse(buf.equals(Boolean.TRUE));
+
+		assertTrue(buf.capacity() > 5);
+
+		buf.limit(buf.capacity()).position(0);
+		readonly.limit(readonly.capacity()).position(1);
+		assertFalse(buf.equals(readonly));
+
+		buf.limit(buf.capacity() - 1).position(0);
+		duplicate.limit(duplicate.capacity()).position(0);
+		assertFalse(buf.equals(duplicate));
+	}
+
+	/*
+	 * Class under test for char get()
+	 */
+	public void testGet() {
+		buf.clear();
+		for (int i = 0; i < buf.capacity(); i++) {
+			assertEquals(buf.position(), i);
+			assertEquals(buf.get(), buf.get(i));
+		}
+		try {
+			buf.get();
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (BufferUnderflowException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Class under test for java.nio.CharBuffer get(char[])
+	 */
+	public void testGetcharArray() {
+		char array[] = new char[1];
+		buf.clear();
+		for (int i = 0; i < buf.capacity(); i++) {
+			assertEquals(buf.position(), i);
+			CharBuffer ret = buf.get(array);
+			assertEquals(array[0], buf.get(i));
+			assertSame(ret, buf);
+		}
+		try {
+			buf.get(array);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (BufferUnderflowException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Class under test for java.nio.CharBuffer get(char[], int, int)
+	 */
+	public void testGetcharArrayintint() {
+		buf.clear();
+		char array[] = new char[buf.capacity()];
+
+		try {
+			buf.get(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (BufferUnderflowException e) {
+			// expected
+		}
+		assertEquals(buf.position(), 0);
+		try {
+			buf.get(array, -1, array.length);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		buf.get(array, array.length, 0);
+		try {
+			buf.get(array, array.length + 1, 1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		assertEquals(buf.position(), 0);
+		try {
+			buf.get(array, 2, -1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+        try {
+            buf.get((char[])null, 2, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            buf.get(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+		assertEquals(buf.position(), 0);
+
+		buf.clear();
+		CharBuffer ret = buf.get(array, 0, array.length);
+		assertEquals(buf.position(), buf.capacity());
+		assertContentEquals(buf, array, 0, array.length);
+		assertSame(ret, buf);
+	}
+
+	/*
+	 * Class under test for char get(int)
+	 */
+	public void testGetint() {
+		buf.clear();
+		for (int i = 0; i < buf.capacity(); i++) {
+			assertEquals(buf.position(), i);
+			assertEquals(buf.get(), buf.get(i));
+		}
+		try {
+			buf.get(-1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			buf.get(buf.limit());
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+	}
+
+	public void testHashCode() {
+		buf.clear();
+		loadTestData1(buf);
+		CharBuffer readonly = buf.asReadOnlyBuffer();
+		CharBuffer duplicate = buf.duplicate();
+		assertTrue(buf.hashCode() == readonly.hashCode());
+		assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+		duplicate.position(buf.capacity() / 2);
+		assertTrue(buf.hashCode() != duplicate.hashCode());
+	}
+
+	/*
+	 * Class under test for java.nio.CharBuffer put(char)
+	 */
+	public void testPutchar() {
+		buf.clear();
+		for (int i = 0; i < buf.capacity(); i++) {
+			assertEquals(buf.position(), i);
+			CharBuffer ret = buf.put((char) i);
+			assertEquals(buf.get(i), (char) i);
+			assertSame(ret, buf);
+		}
+		try {
+			buf.put((char) 0);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (BufferOverflowException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Class under test for java.nio.CharBuffer put(char[])
+	 */
+	public void testPutcharArray() {
+		char array[] = new char[1];
+
+		buf.clear();
+		for (int i = 0; i < buf.capacity(); i++) {
+			assertEquals(buf.position(), i);
+			array[0] = (char) i;
+			CharBuffer ret = buf.put(array);
+			assertEquals(buf.get(i), (char) i);
+			assertSame(ret, buf);
+		}
+		try {
+			buf.put(array);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (BufferOverflowException e) {
+			// expected
+		}
+		try {
+			buf.put((char[]) null);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Class under test for java.nio.CharBuffer put(char[], int, int)
+	 */
+	public void testPutcharArrayintint() {
+		buf.clear();
+		char array[] = new char[buf.capacity()];
+		try {
+			buf.put((char[]) null, 0, 1);
+			fail("Should throw NullPointerException"); //$NON-NLS-1$
+		} catch (NullPointerException e) {
+			// expected
+		}
+		try {
+			buf.put(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (BufferOverflowException e) {
+			// expected
+		}
+		assertEquals(buf.position(), 0);
+		try {
+			buf.put(array, -1, array.length);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			buf.put(array, array.length + 1, 0);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		buf.put(array, array.length, 0);
+		assertEquals(buf.position(), 0);
+		try {
+			buf.put(array, 0, -1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+        try {
+            buf.put((char[])null, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+		assertEquals(buf.position(), 0);
+
+		loadTestData2(array, 0, array.length);
+		CharBuffer ret = buf.put(array, 0, array.length);
+		assertEquals(buf.position(), buf.capacity());
+		assertContentEquals(buf, array, 0, array.length);
+		assertSame(ret, buf);
+	}
+
+	/*
+	 * Class under test for java.nio.CharBuffer put(java.nio.CharBuffer)
+	 */
+	public void testPutCharBuffer() {
+		CharBuffer other = CharBuffer.allocate(buf.capacity());
+
+		try {
+			buf.put((CharBuffer) null);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (NullPointerException e) {
+			// expected
+		}
+		try {
+			buf.put(buf);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+		try {
+			buf.put(CharBuffer.allocate(buf.capacity() + 1));
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (BufferOverflowException e) {
+			// expected
+		}
+        try {
+            buf.flip();
+            buf.put((CharBuffer)null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+		loadTestData2(other);
+		other.clear();
+		buf.clear();
+		CharBuffer ret = buf.put(other);
+		assertEquals(other.position(), other.capacity());
+		assertEquals(buf.position(), buf.capacity());
+		assertContentEquals(other, buf);
+		assertSame(ret, buf);
+	}
+
+	/*
+	 * Class under test for java.nio.CharBuffer put(int, char)
+	 */
+	public void testPutintchar() {
+		buf.clear();
+		for (int i = 0; i < buf.capacity(); i++) {
+			assertEquals(buf.position(), 0);
+			CharBuffer ret = buf.put(i, (char) i);
+			assertEquals(buf.get(i), (char) i);
+			assertSame(ret, buf);
+		}
+		try {
+			buf.put(-1, (char) 0);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			buf.put(buf.limit(), (char) 0);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+	}
+
+	public void testSlice() {
+		assertTrue(buf.capacity() > 5);
+		buf.position(1);
+		buf.limit(buf.capacity() - 1);
+
+		CharBuffer slice = buf.slice();
+		assertEquals(buf.isReadOnly(), slice.isReadOnly());
+		assertEquals(buf.isDirect(), slice.isDirect());
+		assertEquals(buf.order(), slice.order());
+		assertEquals(slice.position(), 0);
+		assertEquals(slice.limit(), buf.remaining());
+		assertEquals(slice.capacity(), buf.remaining());
+		try {
+			slice.reset();
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (InvalidMarkException e) {
+			// expected
+		}
+
+		// slice share the same content with buf
+		if (!slice.isReadOnly()) {
+			loadTestData1(slice);
+			assertContentLikeTestData1(buf, 1, (char) 0, slice.capacity());
+			buf.put(2, (char) 500);
+			assertEquals(slice.get(1), 500);
+		}
+	}
+
+	public void testToString() {
+		String expected = "";
+		for (int i = buf.position(); i < buf.limit(); i++) {
+			expected += buf.get(i);
+		}
+		String str = buf.toString();
+		assertEquals(expected, str);
+	}
+
+	public void testCharAt() {
+		for (int i = 0; i < buf.remaining(); i++) {
+			assertEquals(buf.get(buf.position() + i), buf.charAt(i));
+		}
+		try {
+			buf.charAt(-1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			buf.charAt(buf.remaining());
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+	}
+
+	public void testLength() {
+		assertEquals(buf.length(), buf.remaining());
+	}
+
+	public void testSubSequence() {
+		try {
+			buf.subSequence(-1, buf.length());
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			buf.subSequence(buf.length() + 1, buf.length() + 1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		assertEquals(buf.subSequence(buf.length(), buf.length()).length(), 0);
+		try {
+			buf.subSequence(1, 0);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			buf.subSequence(1, buf.length() + 1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+
+		assertEquals(buf.subSequence(0, buf.length()).toString(), buf
+				.toString());
+
+		if (buf.length() >= 2) {
+			assertEquals(buf.subSequence(1, buf.length() - 1).toString(), buf
+					.toString().substring(1, buf.length() - 1));
+		}
+	}
+
+	public void testPutString() {
+		String str = " ";
+
+		buf.clear();
+		for (int i = 0; i < buf.capacity(); i++) {
+			assertEquals(buf.position(), i);
+			str = "" + (char) i;
+			CharBuffer ret = buf.put(str);
+			assertEquals(buf.get(i), (char) i);
+			assertSame(ret, buf);
+		}
+		try {
+			buf.put(str);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (BufferOverflowException e) {
+			// expected
+		}
+		try {
+			buf.put((String) null);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	public void testPutStringintint() {
+		buf.clear();
+		String str = String.valueOf(new char[buf.capacity()]);
+
+		// Throw a BufferOverflowException and no character is transfered to
+		// CharBuffer
+		try {
+			buf.put(String.valueOf(new char[buf.capacity() + 1]), 0, buf
+					.capacity() + 1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (BufferOverflowException e) {
+			// expected
+		}
+		try {
+			buf.put((String) null, 0, buf.capacity() + 1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (NullPointerException e) {
+			// expected
+		}
+		assertEquals(0, buf.position());
+
+		buf.clear();
+		try {
+			buf.put(str, -1, str.length());
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			buf.put(str, str.length() + 1, str.length() + 2);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			buf.put((String) null, -1, 0);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (NullPointerException e) {
+			// expected
+		}
+		buf.put(str, str.length(), str.length());
+		assertEquals(buf.position(), 0);
+		try {
+			buf.put(str, 2, 1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			buf.put(str, 2, str.length() + 1);
+			fail("Should throw Exception"); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		assertEquals(buf.position(), 0);
+
+		char array[] = new char[buf.capacity()];
+		loadTestData2(array, 0, array.length);
+		str = String.valueOf(array);
+
+		CharBuffer ret = buf.put(str, 0, str.length());
+		assertEquals(buf.position(), buf.capacity());
+		assertContentEquals(buf, str.toCharArray(), 0, str.length());
+		assertSame(ret, buf);
+	}
+
+	void loadTestData1(char array[], int offset, int length) {
+		for (int i = 0; i < length; i++) {
+			array[offset + i] = (char) i;
+		}
+	}
+
+	void loadTestData2(char array[], int offset, int length) {
+		for (int i = 0; i < length; i++) {
+			array[offset + i] = (char) (length - i);
+		}
+	}
+
+	void loadTestData1(CharBuffer buf) {
+		buf.clear();
+		for (int i = 0; i < buf.capacity(); i++) {
+			buf.put(i, (char) i);
+		}
+	}
+
+	void loadTestData2(CharBuffer buf) {
+		buf.clear();
+		for (int i = 0; i < buf.capacity(); i++) {
+			buf.put(i, (char) (buf.capacity() - i));
+		}
+	}
+
+	private void assertContentEquals(CharBuffer buf, char array[], int offset,
+			int length) {
+		for (int i = 0; i < length; i++) {
+			assertEquals(buf.get(i), array[offset + i]);
+		}
+	}
+
+	private void assertContentEquals(CharBuffer buf, CharBuffer other) {
+		assertEquals(buf.capacity(), other.capacity());
+		for (int i = 0; i < buf.capacity(); i++) {
+			assertEquals(buf.get(i), other.get(i));
+		}
+	}
+
+	private void assertContentLikeTestData1(CharBuffer buf, int startIndex,
+			char startValue, int length) {
+		char value = startValue;
+		for (int i = 0; i < length; i++) {
+			assertEquals(buf.get(startIndex + i), value);
+			value = (char) (value + 1);
+		}
+	}
+
+	public void testAppendSelf() throws Exception {
+		CharBuffer cb = CharBuffer.allocate(10);
+		CharBuffer cb2 = cb.duplicate();
+		cb.append(cb);
+		assertEquals(10, cb.position());
+		cb.clear();
+		assertEquals(cb2, cb);
+
+		cb.put("abc");
+		cb2 = cb.duplicate();
+		cb.append(cb);
+		assertEquals(10, cb.position());
+		cb.clear();
+		cb2.clear();
+		assertEquals(cb2, cb);
+
+		cb.put("edfg");
+		cb.clear();
+		cb2 = cb.duplicate();
+		cb.append(cb);
+		assertEquals(10, cb.position());
+		cb.clear();
+		cb2.clear();
+		assertEquals(cb, cb2);
+	}
+
+	public void testAppendOverFlow() throws IOException {
+		CharBuffer cb = CharBuffer.allocate(1);
+		CharSequence cs = "String";
+		cb.put('A');
+		try {
+			cb.append('C');
+			fail("should throw BufferOverflowException.");
+		} catch (BufferOverflowException ex) {
+			// expected;
+		}
+		try {
+			cb.append(cs);
+			fail("should throw BufferOverflowException.");
+		} catch (BufferOverflowException ex) {
+			// expected;
+		}
+		try {
+			cb.append(cs, 1, 2);
+			fail("should throw BufferOverflowException.");
+		} catch (BufferOverflowException ex) {
+			// expected;
+		}
+	}
+
+	public void testReadOnlyMap() throws IOException {
+		CharBuffer cb = CharBuffer.wrap("ABCDE").asReadOnlyBuffer();
+		CharSequence cs = "String";
+		try {
+			cb.append('A');
+			fail("should throw ReadOnlyBufferException.");
+		} catch (ReadOnlyBufferException ex) {
+			// expected;
+		}
+		try {
+			cb.append(cs);
+			fail("should throw ReadOnlyBufferException.");
+		} catch (ReadOnlyBufferException ex) {
+			// expected;
+		}
+		try {
+			cb.append(cs, 1, 2);
+			fail("should throw ReadOnlyBufferException.");
+		} catch (ReadOnlyBufferException ex) {
+			// expected;
+		}
+		cb.append(cs, 1, 1);
+	}
+
+	public void testAppendCNormal() throws IOException {
+		CharBuffer cb = CharBuffer.allocate(2);
+		cb.put('A');
+		assertSame(cb, cb.append('B'));
+		assertEquals('B', cb.get(1));
+	}
+
+	public void testAppendCharSequenceNormal() throws IOException {
+		CharBuffer cb = CharBuffer.allocate(10);
+		cb.put('A');
+		assertSame(cb, cb.append("String"));
+		assertEquals("AString", cb.flip().toString());
+		cb.append(null);
+		assertEquals("null", cb.flip().toString());
+	}
+
+	public void testAppendCharSequenceIINormal() throws IOException {
+		CharBuffer cb = CharBuffer.allocate(10);
+		cb.put('A');
+		assertSame(cb, cb.append("String", 1, 3));
+		assertEquals("Atr", cb.flip().toString());
+
+		cb.append(null, 0, 1);
+		assertEquals("n", cb.flip().toString());
+	}
+
+	public void testAppendCharSequenceII_IllegalArgument() throws IOException {
+		CharBuffer cb = CharBuffer.allocate(10);
+		cb.append("String", 0, 0);
+		cb.append("String", 2, 2);
+		try {
+			cb.append("String", -1, 1);
+			fail("should throw IndexOutOfBoundsException.");
+		} catch (IndexOutOfBoundsException ex) {
+			// expected;
+		}
+		try {
+			cb.append("String", -1, -1);
+			fail("should throw IndexOutOfBoundsException.");
+		} catch (IndexOutOfBoundsException ex) {
+			// expected;
+		}
+		try {
+			cb.append("String", 3, 2);
+			fail("should throw IndexOutOfBoundsException.");
+		} catch (IndexOutOfBoundsException ex) {
+			// expected;
+		}
+		try {
+			cb.append("String", 3, 0);
+			fail("should throw IndexOutOfBoundsException.");
+		} catch (IndexOutOfBoundsException ex) {
+			// expected;
+		}
+		try {
+			cb.append("String", 3, 110);
+			fail("should throw IndexOutOfBoundsException.");
+		} catch (IndexOutOfBoundsException ex) {
+			// expected;
+		}
+	}
+
+	public void testReadCharBuffer() throws IOException {
+		CharBuffer source = CharBuffer.wrap("String");
+		CharBuffer target = CharBuffer.allocate(10);
+		assertEquals(6, source.read(target));
+		assertEquals("String", target.flip().toString());
+		// return -1 when nothing to read
+		assertEquals(-1, source.read(target));
+		// NullPointerException
+		try {
+			assertEquals(-1, source.read(null));
+			fail("should throw NullPointerException.");
+		} catch (NullPointerException ex) {
+			// expected;
+		}
+
+	}
+
+	public void testReadReadOnly() throws IOException {
+		CharBuffer source = CharBuffer.wrap("String");
+		CharBuffer target = CharBuffer.allocate(10).asReadOnlyBuffer();
+		try {
+			source.read(target);
+			fail("should throw ReadOnlyBufferException.");
+		} catch (ReadOnlyBufferException ex) {
+			// expected;
+		}
+		// if target has no remaining, needn't to check the isReadOnly
+		target.flip();
+		assertEquals(0, source.read(target));
+	}
+
+	public void testReadOverflow() throws IOException {
+		CharBuffer source = CharBuffer.wrap("String");
+		CharBuffer target = CharBuffer.allocate(1);
+		assertEquals(1, source.read(target));
+		assertEquals("S", target.flip().toString());
+		assertEquals(1, source.position());
+	}
+
+	public void testReadSelf() throws Exception {
+		CharBuffer source = CharBuffer.wrap("abuffer");
+		try {
+			source.read(source);
+			fail("should throw IAE.");
+		} catch (IllegalArgumentException e) {
+            //expected
+		}
+	}
+
+    public void testRead_scenario1() throws Exception {
+        char[] charArray = new char[] { 'a', 'b' };
+        CharBuffer charBuffer = CharBuffer.wrap(charArray);
+        try {
+            charBuffer.read(charBuffer);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        charBuffer.put(charArray);
+        assertEquals(-1, charBuffer.read(charBuffer));
+    }
+
+    public void testRead_scenario2() throws Exception {
+        CharBuffer charBufferA = CharBuffer.allocate(0);
+        CharBuffer allocateBuffer = CharBuffer.allocate(1);
+        CharBuffer charBufferB = CharBuffer.wrap(allocateBuffer);
+        assertEquals(-1, charBufferA.read(charBufferB));
+
+        allocateBuffer.append(allocateBuffer);
+        charBufferB = CharBuffer.wrap(allocateBuffer);
+        assertEquals(-1, charBufferA.read(charBufferB));
+    }
+
+	public void testIsDirect() {
+		assertFalse(buf.isDirect());
+	}
+
+	public void testHasArray() {
+		assertTrue(buf.hasArray());
+	}
+
+	public void testOrder() {
+		assertEquals(ByteOrder.nativeOrder(), buf.order());
+	}
+
+	public void testIsReadOnly() {
+		assertFalse(buf.isReadOnly());
+	}
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectByteBufferTest.java
new file mode 100644
index 0000000..f274676
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectByteBufferTest.java
@@ -0,0 +1,60 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+
+public class DirectByteBufferTest extends ByteBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = ByteBuffer.allocateDirect(BUFFER_LENGTH);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        buf = null;
+        baseBuf = null;
+    }
+
+    /**
+     * @tests java.nio.ByteBuffer#allocateDirect(int)
+     *
+     */
+    public void testAllocatedByteBuffer_IllegalArg() {
+        try {
+            ByteBuffer.allocateDirect(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void testIsDirect() {
+        assertTrue(buf.isDirect());
+    }
+
+    public void testHasArray() {
+        // Android direct byte buffers have backing arrays.
+        assertTrue(buf.hasArray());
+        // assertFalse(buf.hasArray());
+    }
+
+    public void testIsReadOnly() {
+        assertFalse(buf.isReadOnly());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectCharBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectCharBufferTest.java
new file mode 100644
index 0000000..83cfc9d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectCharBufferTest.java
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectCharBufferTest extends CharBufferTest {
+    
+    public void setUp(){
+        buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*2).asCharBuffer();
+        super.loadTestData1(buf);
+        baseBuf = buf;
+    }
+    
+    public void tearDown(){
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+    
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+
+    public void testIsDirect() {
+        assertTrue(buf.isDirect());
+    }
+    
+    public void testOrder() {
+        assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectDoubleBufferTest.java
new file mode 100644
index 0000000..561c0fa
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectDoubleBufferTest.java
@@ -0,0 +1,60 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectDoubleBufferTest extends DoubleBufferTest {
+    public void setUp(){
+        buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*8).asDoubleBuffer();
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+    
+    public void tearDown(){
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+    
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+
+    public void testIsDirect() {
+        assertTrue(buf.isDirect());
+    }
+    
+    public void testOrder() {
+        assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectFloatBufferTest.java
new file mode 100644
index 0000000..8739c1b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectFloatBufferTest.java
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectFloatBufferTest extends FloatBufferTest {
+    public void setUp(){
+        buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*4).asFloatBuffer();
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+    
+    public void tearDown(){
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+    
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+            //expected
+        }
+    }
+
+    public void testIsDirect() {
+        assertTrue(buf.isDirect());
+    }
+    
+    public void testOrder() {
+        assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectIntBufferTest.java
new file mode 100644
index 0000000..393366e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectIntBufferTest.java
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectIntBufferTest extends IntBufferTest {
+    public void setUp(){
+        buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*4).asIntBuffer();
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+    
+    public void tearDown(){
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+    
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+            //expected
+        }
+    }
+
+    public void testIsDirect() {
+        assertTrue(buf.isDirect());
+    }
+    
+    public void testOrder() {
+        assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectLongBufferTest.java
new file mode 100644
index 0000000..245cd25
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectLongBufferTest.java
@@ -0,0 +1,62 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+
+public class DirectLongBufferTest extends LongBufferTest {
+    public void setUp(){
+        buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*8).asLongBuffer();
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+    
+    public void tearDown(){
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+    
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+            //expected
+        }
+    }
+
+    public void testIsDirect() {
+        assertTrue(buf.isDirect());
+    }
+    
+    public void testOrder() {
+        assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectShortBufferTest.java
new file mode 100644
index 0000000..9ae290a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectShortBufferTest.java
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectShortBufferTest extends ShortBufferTest {
+    public void setUp(){
+        buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*2).asShortBuffer();
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+    
+    public void tearDown(){
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+    
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+            //expected
+        }
+    }
+
+    public void testIsDirect() {
+        assertTrue(buf.isDirect());
+    }
+    
+    public void testOrder() {
+        assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java
new file mode 100644
index 0000000..40ff2e0
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java
@@ -0,0 +1,664 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.DoubleBuffer;
+import java.nio.InvalidMarkException;
+
+/**
+ * Tests java.nio.DoubleBuffer
+ */
+public class DoubleBufferTest extends AbstractBufferTest {
+
+    protected static final int SMALL_TEST_LENGTH = 5;
+
+    protected static final int BUFFER_LENGTH = 20;
+
+    protected DoubleBuffer buf;
+
+    protected void setUp() throws Exception {
+        buf = DoubleBuffer.allocate(BUFFER_LENGTH);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        buf = null;
+        baseBuf = null;
+    }
+
+    /*
+     * Test with bit sequences that represent the IEEE754 doubles Positive
+     * infinity, negative infinity, and NaN.
+     */
+    public void testNaNs() {
+        long[] nans = new long[] { 0x7ff0000000000000L, 0xfff0000000000000L,
+                0x7ff8000000000000L };
+        for (int i = 0; i < nans.length; i++) {
+            long longBitsIn = nans[i];
+            double dbl = Double.longBitsToDouble(longBitsIn);
+            long longBitsOut = Double.doubleToRawLongBits(dbl);
+            // Sanity check
+            assertTrue(longBitsIn == longBitsOut);
+
+            // Store the double and retrieve it
+            ByteBuffer buffer = ByteBuffer.allocate(8);
+            buffer.putDouble(dbl);
+            double bufDoubleOut = buffer.getDouble(0);
+
+            // Check the bits sequence was not normalized
+            long bufLongOut = Double.doubleToRawLongBits(bufDoubleOut);
+            assertTrue(longBitsIn == bufLongOut);
+        }
+    }
+
+    public void testArray() {
+        double array[] = buf.array();
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+    }
+
+    public void testArrayOffset() {
+        double array[] = buf.array();
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+    }
+
+    public void testAsReadOnlyBuffer() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // readonly's contents should be the same as buf
+        DoubleBuffer readonly = buf.asReadOnlyBuffer();
+        assertNotSame(buf, readonly);
+        assertTrue(readonly.isReadOnly());
+        assertEquals(buf.position(), readonly.position());
+        assertEquals(buf.limit(), readonly.limit());
+        assertEquals(buf.isDirect(), readonly.isDirect());
+        assertEquals(buf.order(), readonly.order());
+        assertContentEquals(buf, readonly);
+
+        // readonly's position, mark, and limit should be independent to buf
+        readonly.reset();
+        assertEquals(readonly.position(), 0);
+        readonly.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+    }
+
+    public void testCompact() {
+        // case: buffer is full
+        buf.clear();
+        buf.mark();
+        loadTestData1(buf);
+        DoubleBuffer ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), buf.capacity());
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 0.0, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: buffer is empty
+        buf.position(0);
+        buf.limit(0);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 0);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 0.0, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: normal
+        assertTrue(buf.capacity() > 5);
+        buf.position(1);
+        buf.limit(5);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 4);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 1.0, 4);
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+    }
+
+    public void testCompareTo() {
+        DoubleBuffer other = DoubleBuffer.allocate(buf.capacity());
+        loadTestData1(other);
+        assertEquals(0, buf.compareTo(other));
+        assertEquals(0, other.compareTo(buf));
+        buf.position(1);
+        assertTrue(buf.compareTo(other) > 0);
+        assertTrue(other.compareTo(buf) < 0);
+        other.position(2);
+        assertTrue(buf.compareTo(other) < 0);
+        assertTrue(other.compareTo(buf) > 0);
+        buf.position(2);
+        other.limit(5);
+        assertTrue(buf.compareTo(other) > 0);
+        assertTrue(other.compareTo(buf) < 0);
+
+        DoubleBuffer dbuffer1 = DoubleBuffer.wrap(new double[] { Double.NaN });
+        DoubleBuffer dbuffer2 = DoubleBuffer.wrap(new double[] { Double.NaN });
+        DoubleBuffer dbuffer3 = DoubleBuffer.wrap(new double[] { 42d });
+
+        assertEquals("Failed equal comparison with NaN entry", 0, dbuffer1
+                .compareTo(dbuffer2));
+        assertEquals("Failed greater than comparison with NaN entry", 1, dbuffer3
+                .compareTo(dbuffer1));
+        assertEquals("Failed greater than comparison with NaN entry", 1, dbuffer1
+                .compareTo(dbuffer3));
+    }
+
+    public void testDuplicate() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // duplicate's contents should be the same as buf
+        DoubleBuffer duplicate = buf.duplicate();
+        assertNotSame(buf, duplicate);
+        assertEquals(buf.position(), duplicate.position());
+        assertEquals(buf.limit(), duplicate.limit());
+        assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+        assertEquals(buf.isDirect(), duplicate.isDirect());
+        assertEquals(buf.order(), duplicate.order());
+        assertContentEquals(buf, duplicate);
+
+        // duplicate's position, mark, and limit should be independent to buf
+        duplicate.reset();
+        assertEquals(duplicate.position(), 0);
+        duplicate.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+
+        // duplicate share the same content with buf
+        // FIXME
+        if (!duplicate.isReadOnly()) {
+            loadTestData1(buf);
+            assertContentEquals(buf, duplicate);
+            loadTestData2(duplicate);
+            assertContentEquals(buf, duplicate);
+        }
+    }
+
+    public void testEquals() {
+        // equal to self
+        assertTrue(buf.equals(buf));
+        DoubleBuffer readonly = buf.asReadOnlyBuffer();
+        assertTrue(buf.equals(readonly));
+        DoubleBuffer duplicate = buf.duplicate();
+        assertTrue(buf.equals(duplicate));
+
+        // always false, if type mismatch
+        assertFalse(buf.equals(Boolean.TRUE));
+
+        assertTrue(buf.capacity() > 5);
+
+        buf.limit(buf.capacity()).position(0);
+        readonly.limit(readonly.capacity()).position(1);
+        assertFalse(buf.equals(readonly));
+
+        buf.limit(buf.capacity() - 1).position(0);
+        duplicate.limit(duplicate.capacity()).position(0);
+        assertFalse(buf.equals(duplicate));
+    }
+
+    /*
+     * Class under test for double get()
+     */
+    public void testGet() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i), 0.01);
+        }
+        try {
+            buf.get();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.DoubleBuffer get(double[])
+     */
+    public void testGetdoubleArray() {
+        double array[] = new double[1];
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            DoubleBuffer ret = buf.get(array);
+            assertEquals(array[0], buf.get(i), 0.01);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.get(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.DoubleBuffer get(double[], int, int)
+     */
+    public void testGetdoubleArrayintint() {
+        buf.clear();
+        double array[] = new double[buf.capacity()];
+
+        try {
+            buf.get(new double[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.get(array, array.length, 0);
+        try {
+            buf.get(array, array.length + 1, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, 2, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get((double[])null, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            buf.get(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+
+        buf.clear();
+        DoubleBuffer ret = buf.get(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for double get(int)
+     */
+    public void testGetint() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i), 0.01);
+        }
+        try {
+            buf.get(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(buf.limit());
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testHasArray() {
+        assertTrue(buf.hasArray());
+    }
+
+    public void testHashCode() {
+        buf.clear();
+        DoubleBuffer readonly = buf.asReadOnlyBuffer();
+        DoubleBuffer duplicate = buf.duplicate();
+        assertTrue(buf.hashCode() == readonly.hashCode());
+
+        assertTrue(buf.capacity() > 5);
+        duplicate.position(buf.capacity() / 2);
+        assertTrue(buf.hashCode() != duplicate.hashCode());
+    }
+
+    public void testIsDirect() {
+        assertFalse(buf.isDirect());
+    }
+
+    public void testOrder() {
+        assertEquals(ByteOrder.nativeOrder(), buf.order());
+    }
+
+    /*
+     * Class under test for java.nio.DoubleBuffer put(double)
+     */
+    public void testPutdouble() {
+
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            DoubleBuffer ret = buf.put((double) i);
+            assertEquals(buf.get(i), (double) i, 0.0);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.DoubleBuffer put(double[])
+     */
+    public void testPutdoubleArray() {
+        double array[] = new double[1];
+
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            array[0] = (double) i;
+            DoubleBuffer ret = buf.put(array);
+            assertEquals(buf.get(i), (double) i, 0.0);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.DoubleBuffer put(double[], int, int)
+     */
+    public void testPutdoubleArrayintint() {
+        buf.clear();
+        double array[] = new double[buf.capacity()];
+
+        try {
+            buf.put(new double[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, array.length + 1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.put(array, array.length, 0);
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put((double[])null, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        assertEquals(buf.position(), 0);
+
+        loadTestData2(array, 0, array.length);
+        DoubleBuffer ret = buf.put(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.DoubleBuffer put(java.nio.DoubleBuffer)
+     */
+    public void testPutDoubleBuffer() {
+        DoubleBuffer other = DoubleBuffer.allocate(buf.capacity());
+
+        try {
+            buf.put(buf);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            buf.put(DoubleBuffer.allocate(buf.capacity() + 1));
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+
+        loadTestData2(other);
+        other.clear();
+        buf.clear();
+        DoubleBuffer ret = buf.put(other);
+        assertEquals(other.position(), other.capacity());
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(other, buf);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.DoubleBuffer put(int, double)
+     */
+    public void testPutintdouble() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), 0);
+            DoubleBuffer ret = buf.put(i, (double) i);
+            assertEquals(buf.get(i), (double) i, 0.0);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(-1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(buf.limit(), 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testSlice() {
+        assertTrue(buf.capacity() > 5);
+        buf.position(1);
+        buf.limit(buf.capacity() - 1);
+
+        DoubleBuffer slice = buf.slice();
+        assertEquals(buf.isReadOnly(), slice.isReadOnly());
+        assertEquals(buf.isDirect(), slice.isDirect());
+        assertEquals(buf.order(), slice.order());
+        assertEquals(slice.position(), 0);
+        assertEquals(slice.limit(), buf.remaining());
+        assertEquals(slice.capacity(), buf.remaining());
+        try {
+            slice.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // slice share the same content with buf
+        // FIXME:
+        if (!slice.isReadOnly()) {
+            loadTestData1(slice);
+            assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+            buf.put(2, 500);
+            assertEquals(slice.get(1), 500, 0.0);
+        }
+    }
+
+    public void testToString() {
+        String str = buf.toString();
+        assertTrue(str.indexOf("Double") >= 0 || str.indexOf("double") >= 0);
+        assertTrue(str.indexOf("" + buf.position()) >= 0);
+        assertTrue(str.indexOf("" + buf.limit()) >= 0);
+        assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+    }
+
+    void loadTestData1(double array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (double) i;
+        }
+    }
+
+    void loadTestData2(double array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (double) length - i;
+        }
+    }
+
+    void loadTestData1(DoubleBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (double) i);
+        }
+    }
+
+    void loadTestData2(DoubleBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (double) buf.capacity() - i);
+        }
+    }
+
+    private void assertContentEquals(DoubleBuffer buf, double array[],
+            int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(i), array[offset + i], 0.01);
+        }
+    }
+
+    private void assertContentEquals(DoubleBuffer buf, DoubleBuffer other) {
+        assertEquals(buf.capacity(), other.capacity());
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.get(i), other.get(i), 0.01);
+        }
+    }
+
+    private void assertContentLikeTestData1(DoubleBuffer buf, int startIndex,
+            double startValue, int length) {
+        double value = startValue;
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(startIndex + i), value, 0.01);
+            value = value + 1.0;
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateDirectByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateDirectByteBufferTest.java
new file mode 100644
index 0000000..656241a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateDirectByteBufferTest.java
@@ -0,0 +1,31 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class DuplicateDirectByteBufferTest extends DirectByteBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = buf.duplicate();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateHeapByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateHeapByteBufferTest.java
new file mode 100644
index 0000000..9f44d7a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateHeapByteBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class DuplicateHeapByteBufferTest extends HeapByteBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = buf.duplicate();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateWrappedByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateWrappedByteBufferTest.java
new file mode 100644
index 0000000..2796b88
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateWrappedByteBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class DuplicateWrappedByteBufferTest extends WrappedByteBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = buf.duplicate();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java
new file mode 100644
index 0000000..cfef096
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java
@@ -0,0 +1,674 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.InvalidMarkException;
+
+/**
+ * Tests java.nio.FloatBuffer
+ * 
+ */
+public class FloatBufferTest extends AbstractBufferTest {
+    
+    protected static final int SMALL_TEST_LENGTH = 5;
+
+    protected static final int BUFFER_LENGTH = 20;
+
+    protected FloatBuffer buf;
+
+    protected void setUp() throws Exception {
+        buf = FloatBuffer.allocate(BUFFER_LENGTH);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        buf = null;
+        baseBuf = null;
+    }
+
+    public void testArray() {
+        float array[] = buf.array();
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+    }
+
+    public void testArrayOffset() {
+        float array[] = buf.array();
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+    }
+
+    public void testAsReadOnlyBuffer() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // readonly's contents should be the same as buf
+        FloatBuffer readonly = buf.asReadOnlyBuffer();
+        assertNotSame(buf, readonly);
+        assertTrue(readonly.isReadOnly());
+        assertEquals(buf.position(), readonly.position());
+        assertEquals(buf.limit(), readonly.limit());
+        assertEquals(buf.isDirect(), readonly.isDirect());
+        assertEquals(buf.order(), readonly.order());
+        assertContentEquals(buf, readonly);
+
+        // readonly's position, mark, and limit should be independent to buf
+        readonly.reset();
+        assertEquals(readonly.position(), 0);
+        readonly.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+    }
+
+    public void testCompact() {
+
+        // case: buffer is full
+        buf.clear();
+        buf.mark();
+        loadTestData1(buf);
+        FloatBuffer ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), buf.capacity());
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 0.0f, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: buffer is empty
+        buf.position(0);
+        buf.limit(0);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 0);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 0.0f, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: normal
+        assertTrue(buf.capacity() > 5);
+        buf.position(1);
+        buf.limit(5);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 4);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 1.0f, 4);
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+    }
+
+    public void testCompareTo() {
+        try {
+            buf.compareTo(null);    
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        
+        // compare to self
+        assertEquals(0, buf.compareTo(buf));
+
+        // normal cases
+        assertTrue(buf.capacity() > 5);
+        buf.clear();
+        FloatBuffer other = FloatBuffer.allocate(buf.capacity());
+        loadTestData1(other);
+        assertEquals(0, buf.compareTo(other));
+        assertEquals(0, other.compareTo(buf));
+        buf.position(1);
+        assertTrue(buf.compareTo(other) > 0);
+        assertTrue(other.compareTo(buf) < 0);
+        other.position(2);
+        assertTrue(buf.compareTo(other) < 0);
+        assertTrue(other.compareTo(buf) > 0);
+        buf.position(2);
+        other.limit(5);
+        assertTrue(buf.compareTo(other) > 0);
+        assertTrue(other.compareTo(buf) < 0);
+        
+        FloatBuffer fbuffer1 = FloatBuffer.wrap(new float[] { Float.NaN });
+        FloatBuffer fbuffer2 = FloatBuffer.wrap(new float[] { Float.NaN });
+        FloatBuffer fbuffer3 = FloatBuffer.wrap(new float[] { 42f });
+
+        assertEquals("Failed equal comparison with NaN entry", 0, fbuffer1
+                .compareTo(fbuffer2));
+        assertEquals("Failed greater than comparison with NaN entry", 1, fbuffer3
+                .compareTo(fbuffer1));
+        assertEquals("Failed greater than comparison with NaN entry", 1, fbuffer1
+                .compareTo(fbuffer3));
+
+    }
+
+    public void testDuplicate() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // duplicate's contents should be the same as buf
+        FloatBuffer duplicate = buf.duplicate();
+        assertNotSame(buf, duplicate);
+        assertEquals(buf.position(), duplicate.position());
+        assertEquals(buf.limit(), duplicate.limit());
+        assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+        assertEquals(buf.isDirect(), duplicate.isDirect());
+        assertEquals(buf.order(), duplicate.order());
+        assertContentEquals(buf, duplicate);
+
+        // duplicate's position, mark, and limit should be independent to buf
+        duplicate.reset();
+        assertEquals(duplicate.position(), 0);
+        duplicate.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+
+        // duplicate share the same content with buf
+        if (!duplicate.isReadOnly()) {
+            loadTestData1(buf);
+            assertContentEquals(buf, duplicate);
+            loadTestData2(duplicate);
+            assertContentEquals(buf, duplicate);
+        }
+    }
+
+    public void testEquals() {
+        // equal to self
+        assertTrue(buf.equals(buf));
+        FloatBuffer readonly = buf.asReadOnlyBuffer();
+        assertTrue(buf.equals(readonly));
+        FloatBuffer duplicate = buf.duplicate();
+        assertTrue(buf.equals(duplicate));
+
+        // always false, if type mismatch
+        assertFalse(buf.equals(Boolean.TRUE));
+
+        assertTrue(buf.capacity() > 5);
+
+        buf.limit(buf.capacity()).position(0);
+        readonly.limit(readonly.capacity()).position(1);
+        assertFalse(buf.equals(readonly));
+
+        buf.limit(buf.capacity() - 1).position(0);
+        duplicate.limit(duplicate.capacity()).position(0);
+        assertFalse(buf.equals(duplicate));
+    }
+
+    /*
+     * Class under test for float get()
+     */
+    public void testGet() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i), 0.01);
+        }
+        try {
+            buf.get();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.FloatBuffer get(float[])
+     */
+    public void testGetfloatArray() {
+        float array[] = new float[1];
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            FloatBuffer ret = buf.get(array);
+            assertEquals(array[0], buf.get(i), 0.01);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.get(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+        try {
+            buf.position(buf.limit());
+            buf.get((float[])null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        buf.get(new float[0]);
+    }
+
+    /*
+     * Class under test for java.nio.FloatBuffer get(float[], int, int)
+     */
+    public void testGetfloatArrayintint() {
+        buf.clear();
+        float array[] = new float[buf.capacity()];
+
+        try {
+            buf.get(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.get(array, array.length, 0);
+        try {
+            buf.get(array, array.length + 1, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, 2, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get((float[])null, 2, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            buf.get(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+
+        buf.clear();
+        FloatBuffer ret = buf.get(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for float get(int)
+     */
+    public void testGetint() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i), 0.01);
+        }
+        try {
+            buf.get(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(buf.limit());
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testHasArray() {
+        assertNotNull(buf.array());
+    }
+
+    public void testHashCode() {
+        buf.clear();
+        FloatBuffer readonly = buf.asReadOnlyBuffer();
+        FloatBuffer duplicate = buf.duplicate();
+        assertTrue(buf.hashCode() == readonly.hashCode());
+
+        assertTrue(buf.capacity() > 5);
+        duplicate.position(buf.capacity() / 2);
+        assertTrue(buf.hashCode() != duplicate.hashCode());
+    }
+
+    public void testIsDirect() {
+        assertFalse(buf.isDirect());
+    }
+
+    public void testOrder() {
+        buf.order();
+        if (buf.hasArray()) {
+            assertEquals(ByteOrder.nativeOrder(), buf.order());
+        }
+    }
+
+    /*
+     * Class under test for java.nio.FloatBuffer put(float)
+     */
+    public void testPutfloat() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            FloatBuffer ret = buf.put((float) i);
+            assertEquals(buf.get(i), (float) i, 0.0);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.FloatBuffer put(float[])
+     */
+    public void testPutfloatArray() {
+        float array[] = new float[1];
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            array[0] = (float) i;
+            FloatBuffer ret = buf.put(array);
+            assertEquals(buf.get(i), (float) i, 0.0);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        try {
+            buf.position(buf.limit());
+            buf.put((float[])null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.FloatBuffer put(float[], int, int)
+     */
+    public void testPutfloatArrayintint() {
+        buf.clear();
+        float array[] = new float[buf.capacity()];
+        try {
+            buf.put(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, array.length + 1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.put(array, array.length, 0);
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put((float[])null, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        assertEquals(buf.position(), 0);
+
+        loadTestData2(array, 0, array.length);
+        FloatBuffer ret = buf.put(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.FloatBuffer put(java.nio.FloatBuffer)
+     */
+    public void testPutFloatBuffer() {
+        FloatBuffer other = FloatBuffer.allocate(buf.capacity());
+        try {
+            buf.put(buf);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            buf.put(FloatBuffer.allocate(buf.capacity() + 1));
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        try {
+            buf.flip();
+            buf.put((FloatBuffer)null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        buf.clear();
+        loadTestData2(other);
+        other.clear();
+        buf.clear();
+        FloatBuffer ret = buf.put(other);
+        assertEquals(other.position(), other.capacity());
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(other, buf);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.FloatBuffer put(int, float)
+     */
+    public void testPutintfloat() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), 0);
+            FloatBuffer ret = buf.put(i, (float) i);
+            assertEquals(buf.get(i), (float) i, 0.0);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(-1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(buf.limit(), 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testSlice() {
+        assertTrue(buf.capacity() > 5);
+        buf.position(1);
+        buf.limit(buf.capacity() - 1);
+
+        FloatBuffer slice = buf.slice();
+        assertEquals(buf.isReadOnly(), slice.isReadOnly());
+        assertEquals(buf.isDirect(), slice.isDirect());
+        assertEquals(buf.order(), slice.order());
+        assertEquals(slice.position(), 0);
+        assertEquals(slice.limit(), buf.remaining());
+        assertEquals(slice.capacity(), buf.remaining());
+        try {
+            slice.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // slice share the same content with buf
+        if (!slice.isReadOnly()) {
+            loadTestData1(slice);
+            assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+            buf.put(2, 500);
+            assertEquals(slice.get(1), 500, 0.0);
+        }
+    }
+
+    public void testToString() {
+        String str = buf.toString();
+        assertTrue(str.indexOf("Float") >= 0 || str.indexOf("float") >= 0);
+        assertTrue(str.indexOf("" + buf.position()) >= 0);
+        assertTrue(str.indexOf("" + buf.limit()) >= 0);
+        assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+    }
+
+    void loadTestData1(float array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (float) i;
+        }
+    }
+
+    void loadTestData2(float array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (float) length - i;
+        }
+    }
+
+    void loadTestData1(FloatBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (float) i);
+        }
+    }
+
+    void loadTestData2(FloatBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (float) buf.capacity() - i);
+        }
+    }
+
+    void assertContentEquals(FloatBuffer buf, float array[],
+            int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(i), array[offset + i], 0.01);
+        }
+    }
+
+    void assertContentEquals(FloatBuffer buf, FloatBuffer other) {
+        assertEquals(buf.capacity(), other.capacity());
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.get(i), other.get(i), 0.01);
+        }
+    }
+
+    void assertContentLikeTestData1(FloatBuffer buf,
+            int startIndex, float startValue, int length) {
+        float value = startValue;
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(startIndex + i), value, 0.01);
+            value = value + 1.0f;
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapByteBufferTest.java
new file mode 100644
index 0000000..2f8e44b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapByteBufferTest.java
@@ -0,0 +1,60 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+
+
+public class HeapByteBufferTest extends ByteBufferTest {
+    
+    protected void setUp() throws Exception {   
+        super.setUp();
+        buf = ByteBuffer.allocate(BUFFER_LENGTH);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        buf = null;
+        baseBuf = null;
+    }
+    
+    /**
+     * @tests java.nio.ByteBuffer#allocate(int)
+     * 
+     */
+    public void testAllocatedByteBuffer_IllegalArg() {
+        try {
+            ByteBuffer.allocate(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected 
+        }
+    }
+    
+    public void testIsDirect() {
+        assertFalse(buf.isDirect());
+    }
+
+    public void testHasArray() {
+        assertTrue(buf.hasArray());
+    }
+
+    public void testIsReadOnly() {
+        assertFalse(buf.isReadOnly());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapCharBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapCharBufferTest.java
new file mode 100644
index 0000000..a0c8d74
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapCharBufferTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+
+public class HeapCharBufferTest extends CharBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = CharBuffer.allocate(BUFFER_LENGTH); 
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testAllocatedCharBuffer_IllegalArg() {
+        try {
+            CharBuffer.allocate(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapDoubleBufferTest.java
new file mode 100644
index 0000000..2985899
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapDoubleBufferTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class HeapDoubleBufferTest extends DoubleBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = DoubleBuffer.allocate(BUFFER_LENGTH); 
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testAllocatedDoubleBuffer_IllegalArg() {
+        try {
+            DoubleBuffer.allocate(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapFloatBufferTest.java
new file mode 100644
index 0000000..f90b34e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapFloatBufferTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class HeapFloatBufferTest extends FloatBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = FloatBuffer.allocate(BUFFER_LENGTH); 
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testAllocatedFloatBuffer_IllegalArg() {
+        try {
+            FloatBuffer.allocate(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapIntBufferTest.java
new file mode 100644
index 0000000..0d68835
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapIntBufferTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class HeapIntBufferTest extends IntBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = IntBuffer.allocate(BUFFER_LENGTH); 
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testAllocatedIntBuffer_IllegalArg() {
+        try {
+            IntBuffer.allocate(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapLongBufferTest.java
new file mode 100644
index 0000000..f4f2ae1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapLongBufferTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class HeapLongBufferTest extends LongBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = LongBuffer.allocate(BUFFER_LENGTH); 
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testAllocatedLongBuffer_IllegalArg() {
+        try {
+            LongBuffer.allocate(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapShortBufferTest.java
new file mode 100644
index 0000000..327a035
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapShortBufferTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class HeapShortBufferTest extends ShortBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = ShortBuffer.allocate(BUFFER_LENGTH); 
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        buf = null;
+        baseBuf = null;
+    }
+    
+    public void testAllocatedShortBuffer_IllegalArg() {
+        try {
+            ShortBuffer.allocate(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/IntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/IntBufferTest.java
new file mode 100644
index 0000000..97babcf
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/IntBufferTest.java
@@ -0,0 +1,650 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+import java.nio.InvalidMarkException;
+
+/**
+ * Tests java.nio.IntBuffer
+ * 
+ */
+public class IntBufferTest extends AbstractBufferTest {
+    
+    
+    protected static final int SMALL_TEST_LENGTH = 5;
+
+    protected static final int BUFFER_LENGTH = 20;
+
+    protected IntBuffer buf;
+
+    protected void setUp() throws Exception {
+        buf = IntBuffer.allocate(BUFFER_LENGTH);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        buf = null;
+        baseBuf = null;
+    }
+
+    public void testArray() {
+        int array[] = buf.array();
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+    }
+
+    public  void testArrayOffset() {
+        int array[] = buf.array();
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+     }
+
+    public  void testAsReadOnlyBuffer() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // readonly's contents should be the same as buf
+        IntBuffer readonly = buf.asReadOnlyBuffer();
+        assertNotSame(buf, readonly);
+        assertTrue(readonly.isReadOnly());
+        assertEquals(buf.position(), readonly.position());
+        assertEquals(buf.limit(), readonly.limit());
+        assertEquals(buf.isDirect(), readonly.isDirect());
+        assertEquals(buf.order(), readonly.order());
+        assertContentEquals(buf, readonly);
+
+        // readonly's position, mark, and limit should be independent to buf
+        readonly.reset();
+        assertEquals(readonly.position(), 0);
+        readonly.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+    }
+
+    public  void testCompact() {
+        // case: buffer is full
+        buf.clear();
+        buf.mark();
+        loadTestData1(buf);
+        IntBuffer ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), buf.capacity());
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: buffer is empty
+        buf.position(0);
+        buf.limit(0);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 0);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: normal
+        assertTrue(buf.capacity() > 5);
+        buf.position(1);
+        buf.limit(5);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 4);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 1, 4);
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+    }
+
+    public  void testCompareTo() {
+        // compare to self
+        assertEquals(0, buf.compareTo(buf));
+
+        // normal cases
+        assertTrue(buf.capacity() > 5);
+        buf.clear();
+        IntBuffer other = IntBuffer.allocate(buf.capacity());
+        loadTestData1(other);
+        assertEquals(0, buf.compareTo(other));
+        assertEquals(0, other.compareTo(buf));
+        buf.position(1);
+        assertTrue(buf.compareTo(other) > 0);
+        assertTrue(other.compareTo(buf) < 0);
+        other.position(2);
+        assertTrue(buf.compareTo(other) < 0);
+        assertTrue(other.compareTo(buf) > 0);
+        buf.position(2);
+        other.limit(5);
+        assertTrue(buf.compareTo(other) > 0);
+        assertTrue(other.compareTo(buf) < 0);
+    }
+
+    public  void testDuplicate() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // duplicate's contents should be the same as buf
+        IntBuffer duplicate = buf.duplicate();
+        assertNotSame(buf, duplicate);
+        assertEquals(buf.position(), duplicate.position());
+        assertEquals(buf.limit(), duplicate.limit());
+        assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+        assertEquals(buf.isDirect(), duplicate.isDirect());
+        assertEquals(buf.order(), duplicate.order());
+        assertContentEquals(buf, duplicate);
+
+        // duplicate's position, mark, and limit should be independent to buf
+        duplicate.reset();
+        assertEquals(duplicate.position(), 0);
+        duplicate.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+
+        // duplicate share the same content with buf
+        if (!duplicate.isReadOnly()) {
+            loadTestData1(buf);
+            assertContentEquals(buf, duplicate);
+            loadTestData2(duplicate);
+            assertContentEquals(buf, duplicate);
+        }
+    }
+
+    public  void testEquals() {
+        // equal to self
+        assertTrue(buf.equals(buf));
+        IntBuffer readonly = buf.asReadOnlyBuffer();
+        assertTrue(buf.equals(readonly));
+        IntBuffer duplicate = buf.duplicate();
+        assertTrue(buf.equals(duplicate));
+
+        // always false, if type mismatch
+        assertFalse(buf.equals(Boolean.TRUE));
+
+        assertTrue(buf.capacity() > 5);
+
+        buf.limit(buf.capacity()).position(0);
+        readonly.limit(readonly.capacity()).position(1);
+        assertFalse(buf.equals(readonly));
+
+        buf.limit(buf.capacity() - 1).position(0);
+        duplicate.limit(duplicate.capacity()).position(0);
+        assertFalse(buf.equals(duplicate));
+    }
+
+    /*
+     * Class under test for int get()
+     */
+    public  void testGet() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i));
+        }
+        try {
+            buf.get();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.IntBuffer get(int[])
+     */
+    public  void testGetintArray() {
+        int array[] = new int[1];
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            IntBuffer ret = buf.get(array);
+            assertEquals(array[0], buf.get(i));
+            assertSame(ret, buf);
+        }
+        try {
+            buf.get(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+        try {
+            buf.get((int[])null);
+            fail("Should throw NPE"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.IntBuffer get(int[], int, int)
+     */
+    public  void testGetintArrayintint() {
+        buf.clear();
+        int array[] = new int[buf.capacity()];
+
+        try {
+            buf.get(new int[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.get(array, array.length, 0);
+        try {
+            buf.get(array, array.length + 1, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, 2, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get((int[])null, 2, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            buf.get(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+
+        buf.clear();
+        IntBuffer ret = buf.get(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for int get(int)
+     */
+    public  void testGetint() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i));
+        }
+        try {
+            buf.get(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(buf.limit());
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public  void testHasArray() {
+        assertNotNull(buf.array());
+    }
+
+    public  void testHashCode() {
+        buf.clear();
+        IntBuffer readonly = buf.asReadOnlyBuffer();
+        IntBuffer duplicate = buf.duplicate();
+        assertTrue(buf.hashCode() == readonly.hashCode());
+
+        assertTrue(buf.capacity() > 5);
+        duplicate.position(buf.capacity() / 2);
+        assertTrue(buf.hashCode() != duplicate.hashCode());
+    }
+
+    public  void testIsDirect() {
+        assertFalse(buf.isDirect());
+    }
+
+    public  void testOrder() {
+        buf.order();
+        assertEquals(ByteOrder.nativeOrder(), buf.order());
+    }
+
+    /*
+     * Class under test for java.nio.IntBuffer put(int)
+     */
+    public  void testPutint() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            IntBuffer ret = buf.put((int) i);
+            assertEquals(buf.get(i), (int) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.IntBuffer put(int[])
+     */
+    public  void testPutintArray() {
+        int array[] = new int[1];
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            array[0] = (int) i;
+            IntBuffer ret = buf.put(array);
+            assertEquals(buf.get(i), (int) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        try {
+            buf.position(buf.limit());
+            buf.put((int[])null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.IntBuffer put(int[], int, int)
+     */
+    public  void testPutintArrayintint() {
+        buf.clear();
+        int array[] = new int[buf.capacity()];
+        try {
+            buf.put(new int[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, array.length + 1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.put(array, array.length, 0);
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put((int[])null, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        assertEquals(buf.position(), 0);
+
+        loadTestData2(array, 0, array.length);
+        IntBuffer ret = buf.put(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.IntBuffer put(java.nio.IntBuffer)
+     */
+    public  void testPutIntBuffer() {
+        IntBuffer other = IntBuffer.allocate(buf.capacity());
+        try {
+            buf.put(buf);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            buf.put(IntBuffer.allocate(buf.capacity() + 1));
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        try {
+            buf.flip();
+            buf.put((IntBuffer)null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        loadTestData2(other);
+        other.clear();
+        buf.clear();
+        IntBuffer ret = buf.put(other);
+        assertEquals(other.position(), other.capacity());
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(other, buf);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.IntBuffer put(int, int)
+     */
+    public  void testPutintint() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), 0);
+            IntBuffer ret = buf.put(i, (int) i);
+            assertEquals(buf.get(i), (int) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(-1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(buf.limit(), 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public  void testSlice() {
+        assertTrue(buf.capacity() > 5);
+        buf.position(1);
+        buf.limit(buf.capacity() - 1);
+
+        IntBuffer slice = buf.slice();
+        assertEquals(buf.isReadOnly(), slice.isReadOnly());
+        assertEquals(buf.isDirect(), slice.isDirect());
+        assertEquals(buf.order(), slice.order());
+        assertEquals(slice.position(), 0);
+        assertEquals(slice.limit(), buf.remaining());
+        assertEquals(slice.capacity(), buf.remaining());
+        try {
+            slice.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // slice share the same content with buf
+        if (!slice.isReadOnly()) {
+            loadTestData1(slice);
+            assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+            buf.put(2, 500);
+            assertEquals(slice.get(1), 500);
+        }
+    }
+
+    public  void testToString() {
+        String str = buf.toString();
+        assertTrue(str.indexOf("Int") >= 0 || str.indexOf("int") >= 0);
+        assertTrue(str.indexOf("" + buf.position()) >= 0);
+        assertTrue(str.indexOf("" + buf.limit()) >= 0);
+        assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+    }
+
+      void loadTestData1(int array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (int) i;
+        }
+    }
+
+      void loadTestData2(int array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (int) length - i;
+        }
+    }
+
+      void loadTestData1(IntBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (int) i);
+        }
+    }
+
+      void loadTestData2(IntBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (int) buf.capacity() - i);
+        }
+    }
+
+      void assertContentEquals(IntBuffer buf, int array[],
+            int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(i), array[offset + i]);
+        }
+    }
+
+      void assertContentEquals(IntBuffer buf, IntBuffer other) {
+        assertEquals(buf.capacity(), other.capacity());
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.get(i), other.get(i));
+        }
+    }
+
+      void assertContentLikeTestData1(IntBuffer buf,
+            int startIndex, int startValue, int length) {
+        int value = startValue;
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(startIndex + i), value);
+            value = value + 1;
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java
new file mode 100644
index 0000000..4b7682d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java
@@ -0,0 +1,51 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.InvalidMarkException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+public class InvalidMarkExceptionTest extends TestCase {
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new InvalidMarkException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new InvalidMarkException());
+    }
+    
+    /**
+     *@tests {@link java.nio.InvalidMarkException#InvalidMarkException()}
+     */
+    public void test_Constructor() {
+        InvalidMarkException exception = new InvalidMarkException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getLocalizedMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/LongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/LongBufferTest.java
new file mode 100644
index 0000000..371351b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/LongBufferTest.java
@@ -0,0 +1,657 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.InvalidMarkException;
+import java.nio.LongBuffer;
+
+/**
+ * Tests java.nio.LongBuffer
+ * 
+ */
+public class LongBufferTest extends AbstractBufferTest {
+    
+    
+    protected static final int SMALL_TEST_LENGTH = 5;
+
+    protected static final int BUFFER_LENGTH = 20;
+
+    protected LongBuffer buf;
+
+    protected void setUp() throws Exception {
+        buf = LongBuffer.allocate(BUFFER_LENGTH);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        buf = null;
+        baseBuf = null;
+    }
+
+    public void testArray() {
+        long array[] = buf.array();
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+    }
+
+    public void testArrayOffset() {
+        long array[] = buf.array();
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+    }
+
+    public void testAsReadOnlyBuffer() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // readonly's contents should be the same as buf
+        LongBuffer readonly = buf.asReadOnlyBuffer();
+        assertNotSame(buf, readonly);
+        assertTrue(readonly.isReadOnly());
+        assertEquals(buf.position(), readonly.position());
+        assertEquals(buf.limit(), readonly.limit());
+        assertEquals(buf.isDirect(), readonly.isDirect());
+        assertEquals(buf.order(), readonly.order());
+        assertContentEquals(buf, readonly);
+
+        // readonly's position, mark, and limit should be independent to buf
+        readonly.reset();
+        assertEquals(readonly.position(), 0);
+        readonly.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+    }
+
+    public void testCompact() {
+        // case: buffer is full
+        buf.clear();
+        buf.mark();
+        loadTestData1(buf);
+        LongBuffer ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), buf.capacity());
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: buffer is empty
+        buf.position(0);
+        buf.limit(0);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 0);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: normal
+        assertTrue(buf.capacity() > 5);
+        buf.position(1);
+        buf.limit(5);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 4);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, 1, 4);
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+    }
+
+    public void testCompareTo() {
+        // compare to self
+        assertEquals(0, buf.compareTo(buf));
+
+        // normal cases
+        assertTrue(buf.capacity() > 5);
+        buf.clear();
+        LongBuffer other = LongBuffer.allocate(buf.capacity());
+        loadTestData1(other);
+        assertEquals(0, buf.compareTo(other));
+        assertEquals(0, other.compareTo(buf));
+        buf.position(1);
+        assertTrue(buf.compareTo(other) > 0);
+        assertTrue(other.compareTo(buf) < 0);
+        other.position(2);
+        assertTrue(buf.compareTo(other) < 0);
+        assertTrue(other.compareTo(buf) > 0);
+        buf.position(2);
+        other.limit(5);
+        assertTrue(buf.compareTo(other) > 0);
+        assertTrue(other.compareTo(buf) < 0);
+    }
+
+    public void testDuplicate() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // duplicate's contents should be the same as buf
+        LongBuffer duplicate = buf.duplicate();
+        assertNotSame(buf, duplicate);
+        assertEquals(buf.position(), duplicate.position());
+        assertEquals(buf.limit(), duplicate.limit());
+        assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+        assertEquals(buf.isDirect(), duplicate.isDirect());
+        assertEquals(buf.order(), duplicate.order());
+        assertContentEquals(buf, duplicate);
+
+        // duplicate's position, mark, and limit should be independent to buf
+        duplicate.reset();
+        assertEquals(duplicate.position(), 0);
+        duplicate.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+
+        // duplicate share the same content with buf
+        if (!duplicate.isReadOnly()) {
+            loadTestData1(buf);
+            assertContentEquals(buf, duplicate);
+            loadTestData2(duplicate);
+            assertContentEquals(buf, duplicate);
+        }
+    }
+
+    public void testEquals() {
+        // equal to self
+        assertTrue(buf.equals(buf));
+        LongBuffer readonly = buf.asReadOnlyBuffer();
+        assertTrue(buf.equals(readonly));
+        LongBuffer duplicate = buf.duplicate();
+        assertTrue(buf.equals(duplicate));
+
+        // always false, if type mismatch
+        assertFalse(buf.equals(Boolean.TRUE));
+
+        assertTrue(buf.capacity() > 5);
+
+        buf.limit(buf.capacity()).position(0);
+        readonly.limit(readonly.capacity()).position(1);
+        assertFalse(buf.equals(readonly));
+
+        buf.limit(buf.capacity() - 1).position(0);
+        duplicate.limit(duplicate.capacity()).position(0);
+        assertFalse(buf.equals(duplicate));
+    }
+
+    /*
+     * Class under test for long get()
+     */
+    public void testGet() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i));
+        }
+        try {
+            buf.get();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.LongBuffer get(long[])
+     */
+    public void testGetlongArray() {
+        long array[] = new long[1];
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            LongBuffer ret = buf.get(array);
+            assertEquals(array[0], buf.get(i));
+            assertSame(ret, buf);
+        }
+        try {
+            buf.get(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+        try {
+            buf.position(buf.limit());
+            buf.get((long[])null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.LongBuffer get(long[], int, int)
+     */
+    public void testGetlongArrayintint() {
+        buf.clear();
+        long array[] = new long[buf.capacity()];
+
+        try {
+            buf.get(new long[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.get(array, array.length, 0);
+        try {
+            buf.get(array, array.length + 1, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, 2, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get((long[])null, 2, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            buf.get(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+
+        buf.clear();
+        LongBuffer ret = buf.get(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for long get(int)
+     */
+    public void testGetint() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i));
+        }
+        try {
+            buf.get(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(buf.limit());
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testHasArray() {
+        assertNotNull(buf.array());
+    }
+
+    public void testHashCode() {
+        buf.clear();
+        LongBuffer readonly = buf.asReadOnlyBuffer();
+        LongBuffer duplicate = buf.duplicate();
+        assertTrue(buf.hashCode() == readonly.hashCode());
+
+        assertTrue(buf.capacity() > 5);
+        duplicate.position(buf.capacity() / 2);
+        assertTrue(buf.hashCode() != duplicate.hashCode());
+    }
+
+    public void testIsDirect() {
+        assertFalse(buf.isDirect());
+    }
+
+    public void testOrder() {
+        buf.order();
+        assertEquals(ByteOrder.nativeOrder(), buf.order());
+    }
+
+    /*
+     * Class under test for java.nio.LongBuffer put(long)
+     */
+    public void testPutlong() {
+         buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            LongBuffer ret = buf.put((long) i);
+            assertEquals(buf.get(i), (long) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.LongBuffer put(long[])
+     */
+    public void testPutlongArray() {
+        long array[] = new long[1];
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            array[0] = (long) i;
+            LongBuffer ret = buf.put(array);
+            assertEquals(buf.get(i), (long) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        try {
+            buf.position(buf.limit());
+            buf.put((long[])null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.LongBuffer put(long[], int, int)
+     */
+    public void testPutlongArrayintint() {
+        buf.clear();
+        long array[] = new long[buf.capacity()];
+        try {
+            buf.put(new long[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, array.length + 1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.put(array, array.length, 0);
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put((long[])null, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        assertEquals(buf.position(), 0);
+
+        loadTestData2(array, 0, array.length);
+        LongBuffer ret = buf.put(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.LongBuffer put(java.nio.LongBuffer)
+     */
+    public void testPutLongBuffer() {
+        LongBuffer other = LongBuffer.allocate(buf.capacity());
+        try {
+            buf.put(buf);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            buf.put(LongBuffer.allocate(buf.capacity() + 1));
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        try {
+            buf.flip();
+            buf.put((LongBuffer)null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        loadTestData2(other);
+        other.clear();
+        buf.clear();
+        LongBuffer ret = buf.put(other);
+        assertEquals(other.position(), other.capacity());
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(other, buf);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.LongBuffer put(int, long)
+     */
+    public void testPutintlong() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), 0);
+            LongBuffer ret = buf.put(i, (long) i);
+            assertEquals(buf.get(i), (long) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(-1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(buf.limit(), 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testSlice() {
+        assertTrue(buf.capacity() > 5);
+        buf.position(1);
+        buf.limit(buf.capacity() - 1);
+
+        LongBuffer slice = buf.slice();
+        assertEquals(buf.isReadOnly(), slice.isReadOnly());
+        assertEquals(buf.isDirect(), slice.isDirect());
+        assertEquals(buf.order(), slice.order());
+        assertEquals(slice.position(), 0);
+        assertEquals(slice.limit(), buf.remaining());
+        assertEquals(slice.capacity(), buf.remaining());
+        try {
+            slice.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // slice share the same content with buf
+        if (!slice.isReadOnly()) {
+            loadTestData1(slice);
+            assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+            buf.put(2, 500);
+            assertEquals(slice.get(1), 500);
+        }
+    }
+
+    public void testToString() {
+        String str = buf.toString();
+        assertTrue(str.indexOf("Long") >= 0 || str.indexOf("long") >= 0);
+        assertTrue(str.indexOf("" + buf.position()) >= 0);
+        assertTrue(str.indexOf("" + buf.limit()) >= 0);
+        assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+    }
+
+    void loadTestData1(long array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (long) i;
+        }
+    }
+
+    void loadTestData2(long array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (long) length - i;
+        }
+    }
+
+    void loadTestData1(LongBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (long) i);
+        }
+    }
+
+    void loadTestData2(LongBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (long) buf.capacity() - i);
+        }
+    }
+
+    void assertContentEquals(LongBuffer buf, long array[],
+            int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(i), array[offset + i]);
+        }
+    }
+
+    void assertContentEquals(LongBuffer buf, LongBuffer other) {
+        assertEquals(buf.capacity(), other.capacity());
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.get(i), other.get(i));
+        }
+    }
+
+    void assertContentLikeTestData1(LongBuffer buf,
+            int startIndex, long startValue, int length) {
+        long value = startValue;
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(startIndex + i), value);
+            value = value + 1;
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/MappedByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/MappedByteBufferTest.java
new file mode 100644
index 0000000..308db21
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/MappedByteBufferTest.java
@@ -0,0 +1,231 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.FileChannel.MapMode;
+
+import junit.framework.TestCase;
+
+public class MappedByteBufferTest extends TestCase {
+
+    File tmpFile, emptyFile;
+    
+    /**
+     * A regression test for failing to correctly set capacity of underlying
+     * wrapped buffer from a mapped byte buffer.
+     */
+    public void testasIntBuffer() throws IOException {
+        // Map file
+        FileInputStream fis = new FileInputStream(tmpFile);
+        FileChannel fc = fis.getChannel();
+        MappedByteBuffer mmb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc
+                .size());
+        int len = mmb.capacity();
+        assertEquals("Got wrong number of bytes", 46, len); //$NON-NLS-1$
+
+        // Read in our 26 bytes
+        for (int i = 0; i < 26; i++) {
+            byte b = mmb.get();
+            assertEquals("Got wrong byte value", (byte) 'A' + i, b); //$NON-NLS-1$
+        }
+
+        // Now convert to an IntBuffer to read our ints
+        IntBuffer ibuffer = mmb.asIntBuffer();
+        for (int i = 0; i < 5; i++) {
+            int val = ibuffer.get();
+            assertEquals("Got wrong int value", i + 1, val); //$NON-NLS-1$
+        }
+        fc.close();
+    }
+    
+    /**
+     * Regression for HARMONY-6315 - FileChannel.map throws IOException
+     * when called with size 0
+     * 
+     * @throws IOException
+     */
+    public void testEmptyBuffer() throws IOException {
+    	// Map empty file
+        FileInputStream fis = new FileInputStream(emptyFile);
+        FileChannel fc = fis.getChannel();
+        MappedByteBuffer mmb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
+        
+        // check non-null
+        assertNotNull("MappedByteBuffer created from empty file should not be null", 
+        		mmb);
+        
+        // check capacity is 0
+        int len = mmb.capacity();
+        assertEquals("MappedByteBuffer created from empty file should have 0 capacity", 
+        		0, len);
+        
+        assertFalse("MappedByteBuffer from empty file shouldn't be backed by an array ", 
+        		mmb.hasArray());
+        
+        try
+        {
+        	byte b = mmb.get();
+        	fail("Calling MappedByteBuffer.get() on empty buffer should throw a BufferUnderflowException");
+        }
+        catch (BufferUnderflowException e)
+        {
+        	// expected behaviour
+        }
+        
+        // test expected exceptions thrown
+        try 
+        {
+        	mmb = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size());
+        	fail("Expected NonWritableChannelException to be thrown");
+        }
+        catch (NonWritableChannelException e)
+        {
+        	// expected behaviour
+        }
+        try
+        {
+        	mmb = fc.map(FileChannel.MapMode.PRIVATE, 0, fc.size());
+        	fail("Expected NonWritableChannelException to be thrown");
+        }
+        catch (NonWritableChannelException e)
+        {
+        	// expected behaviour
+        }
+        fc.close();
+    }
+    
+    /**
+     * @tests {@link java.nio.MappedByteBuffer#force()}
+     */
+    public void test_force() throws IOException {
+        // buffer was not mapped in read/write mode
+        FileInputStream fileInputStream = new FileInputStream(tmpFile);
+        FileChannel fileChannelRead = fileInputStream.getChannel();
+        MappedByteBuffer mmbRead = fileChannelRead.map(MapMode.READ_ONLY, 0,
+                fileChannelRead.size());
+
+        mmbRead.force();
+
+        FileInputStream inputStream = new FileInputStream(tmpFile);
+        FileChannel fileChannelR = inputStream.getChannel();
+        MappedByteBuffer resultRead = fileChannelR.map(MapMode.READ_ONLY, 0,
+                fileChannelR.size());
+
+        //If this buffer was not mapped in read/write mode, then invoking this method has no effect.
+        assertEquals(
+                "Invoking force() should have no effect when this buffer was not mapped in read/write mode",
+                mmbRead, resultRead);
+
+        // Buffer was mapped in read/write mode
+        RandomAccessFile randomFile = new RandomAccessFile(tmpFile, "rw");
+        FileChannel fileChannelReadWrite = randomFile.getChannel();
+        MappedByteBuffer mmbReadWrite = fileChannelReadWrite.map(
+                FileChannel.MapMode.READ_WRITE, 0, fileChannelReadWrite.size());
+
+        mmbReadWrite.put((byte) 'o');
+        mmbReadWrite.force();
+
+        RandomAccessFile random = new RandomAccessFile(tmpFile, "rw");
+        FileChannel fileChannelRW = random.getChannel();
+        MappedByteBuffer resultReadWrite = fileChannelRW.map(
+                FileChannel.MapMode.READ_WRITE, 0, fileChannelRW.size());
+
+        // Invoking force() will change the buffer
+        assertFalse(mmbReadWrite.equals(resultReadWrite));
+        
+        fileChannelRead.close();
+        fileChannelR.close();
+        fileChannelReadWrite.close();
+        fileChannelRW.close();
+    }
+
+    /**
+     * @tests {@link java.nio.MappedByteBuffer#load()}
+     */
+    public void test_load() throws IOException {
+        FileInputStream fileInputStream = new FileInputStream(tmpFile);
+        FileChannel fileChannelRead = fileInputStream.getChannel();
+        MappedByteBuffer mmbRead = fileChannelRead.map(MapMode.READ_ONLY, 0,
+                fileChannelRead.size());
+        
+        assertEquals(mmbRead, mmbRead.load());
+
+        RandomAccessFile randomFile = new RandomAccessFile(tmpFile, "rw");
+        FileChannel fileChannelReadWrite = randomFile.getChannel();
+        MappedByteBuffer mmbReadWrite = fileChannelReadWrite.map(
+                FileChannel.MapMode.READ_WRITE, 0, fileChannelReadWrite.size());
+
+        assertEquals(mmbReadWrite, mmbReadWrite.load());
+        
+        fileChannelRead.close();
+        fileChannelReadWrite.close();
+    }
+
+    protected void setUp() throws IOException {
+        // Create temp file with 26 bytes and 5 ints
+        tmpFile = File.createTempFile("harmony", "test");  //$NON-NLS-1$//$NON-NLS-2$
+        tmpFile.deleteOnExit();
+        FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
+        FileChannel fileChannel = fileOutputStream.getChannel();
+        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(26 + 20);
+        for (int i = 0; i < 26; i++) {
+            byteBuffer.put((byte) ('A' + i));
+        }
+        for (int i = 0; i < 5; i++) {
+            byteBuffer.putInt(i + 1);
+        }
+        byteBuffer.rewind();
+        fileChannel.write(byteBuffer);
+        fileChannel.close();
+        fileOutputStream.close();
+        
+        emptyFile = File.createTempFile("harmony", "test");  //$NON-NLS-1$//$NON-NLS-2$
+        emptyFile.deleteOnExit();
+    }
+
+    public void test_position() throws IOException {
+        File tmp = File.createTempFile("hmy", "tmp");
+        tmp.deleteOnExit();
+        RandomAccessFile f = new RandomAccessFile(tmp, "rw");
+        FileChannel ch = f.getChannel();
+        MappedByteBuffer mbb = ch.map(MapMode.READ_WRITE, 0L, 100L);
+        ch.close();
+
+        mbb.putInt(1, 1);
+        mbb.position(50);
+        mbb.putInt(50);
+
+        mbb.flip();
+        mbb.get();
+        assertEquals(1, mbb.getInt());
+
+        mbb.position(50);
+        assertEquals(50, mbb.getInt());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java
new file mode 100644
index 0000000..cbacbc5
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java
@@ -0,0 +1,51 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ReadOnlyBufferException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+public class ReadOnlyBufferExceptionTest extends TestCase {
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new ReadOnlyBufferException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new ReadOnlyBufferException());
+    }
+    
+    /**
+     *@tests {@link java.nio.ReadOnlyBufferException#ReadOnlyBufferException()}
+     */
+    public void test_Constructor() {
+        ReadOnlyBufferException exception = new ReadOnlyBufferException();
+        assertNull(exception.getMessage());
+        assertNull(exception.getLocalizedMessage());
+        assertNull(exception.getCause());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyCharBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyCharBufferTest.java
new file mode 100644
index 0000000..f951962
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyCharBufferTest.java
@@ -0,0 +1,209 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.CharBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyCharBufferTest extends CharBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        buf = null;
+        baseBuf = null;
+        super.tearDown();
+    }
+
+    public void testIsReadOnly() {
+        assertTrue(buf.isReadOnly());
+    }
+
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+        }
+    }
+
+    public void testHashCode() {
+        CharBuffer duplicate = buf.duplicate();
+        assertEquals(buf.hashCode(), duplicate.hashCode());
+    }
+
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+
+    public void testCompact() {
+        try {
+            buf.compact();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutchar() {
+        try {
+            buf.put((char) 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutcharArray() {
+        char array[] = new char[1];
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((char[]) null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    public void testPutcharArrayintint() {
+        char array[] = new char[1];
+        try {
+            buf.put(array, 0, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((char[]) null, 0, 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutCharBuffer() {
+        CharBuffer other = CharBuffer.allocate(1);
+        try {
+            buf.put(other);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((CharBuffer) null);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(buf);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutintchar() {
+        try {
+            buf.put(0, (char) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(-1, (char) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutStringintint() {
+        buf.clear();
+        String str = String.valueOf(new char[buf.capacity()]);
+        try {
+            buf.put(str, 0, str.length());
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((String) null, 0, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException expected) {
+        } catch (NullPointerException expected) {
+        }
+        try {
+            buf.put(str, -1, str.length());
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException expected) {
+        } catch (NullPointerException expected) {
+        }
+        String longStr = String.valueOf(new char[buf.capacity()+1]);
+        try {
+            buf.put(longStr, 0, longStr.length());
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutString() {
+        String str = " ";
+        try {
+            buf.put(str);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((String)null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDirectByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDirectByteBufferTest.java
new file mode 100644
index 0000000..20c7914
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDirectByteBufferTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class ReadOnlyDirectByteBufferTest extends DirectByteBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+    
+    public void testIsReadOnly() {
+        assertTrue(buf.isReadOnly());
+    }
+    
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+    
+    public void testHashCode() {
+        super.readOnlyHashCode();
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDoubleBufferTest.java
new file mode 100644
index 0000000..d87e81d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDoubleBufferTest.java
@@ -0,0 +1,160 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyDoubleBufferTest extends DoubleBufferTest {
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		buf = buf.asReadOnlyBuffer();
+		baseBuf = buf;
+	}
+
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+    public void testIsReadOnly() {
+        assertTrue(buf.isReadOnly());
+    }
+
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+        }
+    }
+
+    public void testHashCode() {
+        DoubleBuffer duplicate = buf.duplicate();
+        assertEquals(buf.hashCode(), duplicate.hashCode());
+    }
+
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+
+    public void testCompact() {
+        try {
+            buf.compact();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutdouble() {
+        try {
+            buf.put(0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutdoubleArray() {
+        double array[] = new double[1];
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((double[]) null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    public void testPutdoubleArrayintint() {
+        double array[] = new double[1];
+        try {
+            buf.put(array, 0, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((double[]) null, 0, 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(new double[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutDoubleBuffer() {
+        DoubleBuffer other = DoubleBuffer.allocate(1);
+        try {
+            buf.put(other);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((DoubleBuffer) null);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(buf);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutintdouble() {
+        try {
+            buf.put(0, (double) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(-1, (double) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyFloatBufferTest.java
new file mode 100644
index 0000000..3acc5c4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyFloatBufferTest.java
@@ -0,0 +1,161 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.FloatBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyFloatBufferTest extends FloatBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testIsReadOnly() {
+        assertTrue(buf.isReadOnly());
+    }
+
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            //expected
+        }
+    }
+
+    public void testHashCode() {
+        FloatBuffer duplicate = buf.duplicate();
+        assertEquals(buf.hashCode(), duplicate.hashCode());
+    }
+
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+            //expected
+        }
+    }
+
+    public void testCompact() {
+        try {
+            buf.compact();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutfloat() {
+        try {
+            buf.put(0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutfloatArray() {
+        float array[] = new float[1];
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((float[]) null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    public void testPutfloatArrayintint() {
+        float array[] = new float[1];
+        try {
+            buf.put(array, 0, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((float[]) null, 0, 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutFloatBuffer() {
+        FloatBuffer other = FloatBuffer.allocate(1);
+        try {
+            buf.put(other);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((FloatBuffer) null);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(buf);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutintfloat() {
+        try {
+            buf.put(0, (float) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(-1, (float) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapByteBufferTest.java
new file mode 100644
index 0000000..7452a24
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapByteBufferTest.java
@@ -0,0 +1,43 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class ReadOnlyHeapByteBufferTest extends HeapByteBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+    
+    public void testIsReadOnly() {
+        assertTrue(buf.isReadOnly());
+    }
+    
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+    
+    public void testHashCode() {
+        super.readOnlyHashCode();    
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapCharBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapCharBufferTest.java
new file mode 100644
index 0000000..4c7792a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapCharBufferTest.java
@@ -0,0 +1,35 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+
+public class ReadOnlyHeapCharBufferTest extends ReadOnlyCharBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = CharBuffer.allocate(BUFFER_LENGTH);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapDoubleBufferTest.java
new file mode 100644
index 0000000..f95c4c2
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapDoubleBufferTest.java
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class ReadOnlyHeapDoubleBufferTest extends ReadOnlyDoubleBufferTest {
+	
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = DoubleBuffer.allocate(BUFFER_LENGTH);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapFloatBufferTest.java
new file mode 100644
index 0000000..f2c6644
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapFloatBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class ReadOnlyHeapFloatBufferTest extends ReadOnlyFloatBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = FloatBuffer.allocate(BUFFER_LENGTH);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapIntBufferTest.java
new file mode 100644
index 0000000..f9a3877
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapIntBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class ReadOnlyHeapIntBufferTest extends ReadOnlyIntBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = IntBuffer.allocate(BUFFER_LENGTH);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapLongBufferTest.java
new file mode 100644
index 0000000..efba978
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapLongBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class ReadOnlyHeapLongBufferTest extends ReadOnlyLongBufferTest{
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = LongBuffer.allocate(BUFFER_LENGTH);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapShortBufferTest.java
new file mode 100644
index 0000000..bbbd616
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapShortBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class ReadOnlyHeapShortBufferTest extends ReadOnlyShortBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = ShortBuffer.allocate(BUFFER_LENGTH);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyIntBufferTest.java
new file mode 100644
index 0000000..61e78a6
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyIntBufferTest.java
@@ -0,0 +1,161 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.IntBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyIntBufferTest extends IntBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testIsReadOnly() {
+        assertTrue(buf.isReadOnly());
+    }
+
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            //expected
+        }
+    }
+
+    public void testHashCode() {
+        IntBuffer duplicate = buf.duplicate();
+        assertEquals(buf.hashCode(), duplicate.hashCode());
+    }
+
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+            //expected
+        }
+    }
+
+    public void testCompact() {
+        try {
+            buf.compact();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutint() {
+        try {
+            buf.put(0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutintArray() {
+        int array[] = new int[1];
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((int[]) null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    public void testPutintArrayintint() {
+        int array[] = new int[1];
+        try {
+            buf.put(array, 0, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((int[]) null, -1, 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(new int[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutIntBuffer() {
+        IntBuffer other = IntBuffer.allocate(1);
+        try {
+            buf.put(other);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((IntBuffer) null);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(buf);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutintint() {
+        try {
+            buf.put(0, (int) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(-1, (int) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyLongBufferTest.java
new file mode 100644
index 0000000..b670606
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyLongBufferTest.java
@@ -0,0 +1,161 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.LongBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyLongBufferTest extends LongBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testIsReadOnly() {
+        assertTrue(buf.isReadOnly());
+    }
+
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            //expected
+        }
+    }
+
+    public void testHashCode() {
+        LongBuffer duplicate = buf.duplicate();
+        assertEquals(buf.hashCode(), duplicate.hashCode());
+    }
+
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+            //expected
+        }
+    }
+
+    public void testCompact() {
+        try {
+            buf.compact();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutlong() {
+        try {
+            buf.put(0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutlongArray() {
+        long array[] = new long[1];
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((long[]) null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    public void testPutlongArrayintint() {
+        long array[] = new long[1];
+        try {
+            buf.put(array, 0, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((long[]) null, 0, 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(new long[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutLongBuffer() {
+        LongBuffer other = LongBuffer.allocate(1);
+        try {
+            buf.put(other);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((LongBuffer) null);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(buf);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutintlong() {
+        try {
+            buf.put(0, (long) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(-1, (long) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyShortBufferTest.java
new file mode 100644
index 0000000..611f6bf
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyShortBufferTest.java
@@ -0,0 +1,161 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ReadOnlyBufferException;
+import java.nio.ShortBuffer;
+
+public class ReadOnlyShortBufferTest extends ShortBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testIsReadOnly() {
+        assertTrue(buf.isReadOnly());
+    }
+
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            //expected
+        }
+    }
+
+    public void testHashCode() {
+        ShortBuffer duplicate = buf.duplicate();
+        assertEquals(buf.hashCode(), duplicate.hashCode());
+    }
+
+    public void testArrayOffset() {
+        try {
+            buf.arrayOffset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+            //expected
+        }
+    }
+
+    public void testCompact() {
+        try {
+            buf.compact();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutshort() {
+        try {
+            buf.put((short)0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutshortArray() {
+        short array[] = new short[1];
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((short[]) null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    public void testPutshortArrayintint() {
+        short array[] = new short[1];
+        try {
+            buf.put(array, 0, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((short[]) null, 0, 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(new short[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutShortBuffer() {
+        ShortBuffer other = ShortBuffer.allocate(1);
+        try {
+            buf.put(other);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((ShortBuffer) null);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(buf);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+
+    public void testPutintshort() {
+        try {
+            buf.put(0, (short) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put(-1, (short) 0);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedByteBufferTest.java
new file mode 100644
index 0000000..031d75b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedByteBufferTest.java
@@ -0,0 +1,45 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class ReadOnlyWrappedByteBufferTest extends WrappedByteBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+    
+    public void testIsReadOnly() {
+        assertTrue(buf.isReadOnly());
+    }
+    
+    public void testHasArray() {
+        assertFalse(buf.hasArray());
+    }
+    
+    public void testHashCode() {
+        super.readOnlyHashCode();
+    }
+
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedCharBufferTest1.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedCharBufferTest1.java
new file mode 100644
index 0000000..57c04bf
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedCharBufferTest1.java
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+public class ReadOnlyWrappedCharBufferTest1 extends ReadOnlyCharBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = CharBuffer.wrap(new char[BUFFER_LENGTH]);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedDoubleBufferTest.java
new file mode 100644
index 0000000..d1ba9df
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedDoubleBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class ReadOnlyWrappedDoubleBufferTest extends ReadOnlyDoubleBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = DoubleBuffer.wrap(new double[BUFFER_LENGTH]);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedFloatBufferTest.java
new file mode 100644
index 0000000..affddaa
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedFloatBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class ReadOnlyWrappedFloatBufferTest extends ReadOnlyFloatBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = FloatBuffer.wrap(new float[BUFFER_LENGTH]);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedIntBufferTest.java
new file mode 100644
index 0000000..a4d0155
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedIntBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class ReadOnlyWrappedIntBufferTest extends ReadOnlyIntBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = IntBuffer.wrap(new int[BUFFER_LENGTH]);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedLongBufferTest.java
new file mode 100644
index 0000000..58491da
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedLongBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class ReadOnlyWrappedLongBufferTest extends ReadOnlyLongBufferTest{
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = LongBuffer.wrap(new long[BUFFER_LENGTH]);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedShortBufferTest.java
new file mode 100644
index 0000000..0ecb3a4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedShortBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class ReadOnlyWrappedShortBufferTest extends ReadOnlyShortBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = ShortBuffer.wrap(new short[BUFFER_LENGTH]);
+        super.loadTestData1(buf);
+        buf = buf.asReadOnlyBuffer();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ShortBufferTest.java
new file mode 100644
index 0000000..98d7659
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ShortBufferTest.java
@@ -0,0 +1,637 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.InvalidMarkException;
+import java.nio.ShortBuffer;
+
+/**
+ * Tests java.nio.ShortBuffer
+ *
+ */
+public class ShortBufferTest extends AbstractBufferTest {
+    
+    protected static final int SMALL_TEST_LENGTH = 5;
+
+    protected static final int BUFFER_LENGTH = 20;
+
+    protected ShortBuffer buf;
+
+    protected void setUp() throws Exception {
+        buf = ShortBuffer.allocate(BUFFER_LENGTH);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        buf = null;
+        baseBuf = null;
+    }
+
+    public void testArray() {
+        short array[] = buf.array();
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+    }
+
+    public void testArrayOffset() {
+        short array[] = buf.array();
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(array, buf.arrayOffset(), buf.capacity());
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData1(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+        loadTestData2(buf);
+        assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+    }
+
+    public void testAsReadOnlyBuffer() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // readonly's contents should be the same as buf
+        ShortBuffer readonly = buf.asReadOnlyBuffer();
+        assertNotSame(buf, readonly);
+        assertTrue(readonly.isReadOnly());
+        assertEquals(buf.position(), readonly.position());
+        assertEquals(buf.limit(), readonly.limit());
+        assertEquals(buf.isDirect(), readonly.isDirect());
+        assertEquals(buf.order(), readonly.order());
+        assertContentEquals(buf, readonly);
+
+        // readonly's position, mark, and limit should be independent to buf
+        readonly.reset();
+        assertEquals(readonly.position(), 0);
+        readonly.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+    }
+
+    public void testCompact() {
+        // case: buffer is full
+        buf.clear();
+        buf.mark();
+        loadTestData1(buf);
+        ShortBuffer ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), buf.capacity());
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, (short) 0, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: buffer is empty
+        buf.position(0);
+        buf.limit(0);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 0);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, (short) 0, buf.capacity());
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // case: normal
+        assertTrue(buf.capacity() > 5);
+        buf.position(1);
+        buf.limit(5);
+        buf.mark();
+        ret = buf.compact();
+        assertSame(ret, buf);
+        assertEquals(buf.position(), 4);
+        assertEquals(buf.limit(), buf.capacity());
+        assertContentLikeTestData1(buf, 0, (short) 1, 4);
+        try {
+            buf.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+    }
+
+    public void testCompareTo() {
+        // compare to self
+        assertEquals(0, buf.compareTo(buf));
+
+        // normal cases
+        assertTrue(buf.capacity() > 5);
+        buf.clear();
+        ShortBuffer other = ShortBuffer.allocate(buf.capacity());
+        loadTestData1(other);
+        assertEquals(0, buf.compareTo(other));
+        assertEquals(0, other.compareTo(buf));
+        buf.position(1);
+        assertTrue(buf.compareTo(other) > 0);
+        assertTrue(other.compareTo(buf) < 0);
+        other.position(2);
+        assertTrue(buf.compareTo(other) < 0);
+        assertTrue(other.compareTo(buf) > 0);
+        buf.position(2);
+        other.limit(5);
+        assertTrue(buf.compareTo(other) > 0);
+        assertTrue(other.compareTo(buf) < 0);
+    }
+
+    public void testDuplicate() {
+        buf.clear();
+        buf.mark();
+        buf.position(buf.limit());
+
+        // duplicate's contents should be the same as buf
+        ShortBuffer duplicate = buf.duplicate();
+        assertNotSame(buf, duplicate);
+        assertEquals(buf.position(), duplicate.position());
+        assertEquals(buf.limit(), duplicate.limit());
+        assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+        assertEquals(buf.isDirect(), duplicate.isDirect());
+        assertEquals(buf.order(), duplicate.order());
+        assertContentEquals(buf, duplicate);
+
+        // duplicate's position, mark, and limit should be independent to buf
+        duplicate.reset();
+        assertEquals(duplicate.position(), 0);
+        duplicate.clear();
+        assertEquals(buf.position(), buf.limit());
+        buf.reset();
+        assertEquals(buf.position(), 0);
+
+        // duplicate share the same content with buf
+        if (!duplicate.isReadOnly()) {
+            loadTestData1(buf);
+            assertContentEquals(buf, duplicate);
+            loadTestData2(duplicate);
+            assertContentEquals(buf, duplicate);
+        }
+    }
+
+    public void testEquals() {
+        // equal to self
+        assertTrue(buf.equals(buf));
+        ShortBuffer readonly = buf.asReadOnlyBuffer();
+        assertTrue(buf.equals(readonly));
+        ShortBuffer duplicate = buf.duplicate();
+        assertTrue(buf.equals(duplicate));
+
+        // always false, if type mismatch
+        assertFalse(buf.equals(Boolean.TRUE));
+
+        assertTrue(buf.capacity() > 5);
+
+        buf.limit(buf.capacity()).position(0);
+        readonly.limit(readonly.capacity()).position(1);
+        assertFalse(buf.equals(readonly));
+
+        buf.limit(buf.capacity() - 1).position(0);
+        duplicate.limit(duplicate.capacity()).position(0);
+        assertFalse(buf.equals(duplicate));
+    }
+
+    /*
+     * Class under test for short get()
+     */
+    public void testGet() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i));
+        }
+        try {
+            buf.get();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.ShortBuffer get(short[])
+     */
+    public void testGetshortArray() {
+        short array[] = new short[1];
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            ShortBuffer ret = buf.get(array);
+            assertEquals(array[0], buf.get(i));
+            assertSame(ret, buf);
+        }
+        try {
+            buf.get(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.ShortBuffer get(short[], int, int)
+     */
+    public void testGetshortArrayintint() {
+        buf.clear();
+        short array[] = new short[buf.capacity()];
+
+        try {
+            buf.get(new short[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.get(array, array.length, 0);
+        try {
+            buf.get(array, array.length + 1, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.get((short[])null, 2, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferUnderflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            buf.get(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+
+        buf.clear();
+        ShortBuffer ret = buf.get(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for short get(int)
+     */
+    public void testGetint() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            assertEquals(buf.get(), buf.get(i));
+        }
+        try {
+            buf.get(-1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.get(buf.limit());
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testHasArray() {
+        assertNotNull(buf.array());
+    }
+
+    public void testHashCode() {
+        buf.clear();
+        ShortBuffer readonly = buf.asReadOnlyBuffer();
+        ShortBuffer duplicate = buf.duplicate();
+        assertTrue(buf.hashCode() == readonly.hashCode());
+
+        assertTrue(buf.capacity() > 5);
+        duplicate.position(buf.capacity() / 2);
+        assertTrue(buf.hashCode() != duplicate.hashCode());
+    }
+
+    public void testIsDirect() {
+        assertFalse(buf.isDirect());
+    }
+
+    public void testOrder() {
+        buf.order();
+        assertEquals(ByteOrder.nativeOrder(), buf.order());
+    }
+
+    /*
+     * Class under test for java.nio.ShortBuffer put(short)
+     */
+    public void testPutshort() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            ShortBuffer ret = buf.put((short) i);
+            assertEquals(buf.get(i), (short) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put((short) 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.ShortBuffer put(short[])
+     */
+    public void testPutshortArray() {
+        short array[] = new short[1];
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), i);
+            array[0] = (short) i;
+            ShortBuffer ret = buf.put(array);
+            assertEquals(buf.get(i), (short) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(array);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        try {
+            buf.position(buf.limit());
+            buf.put((short[])null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /*
+     * Class under test for java.nio.ShortBuffer put(short[], int, int)
+     */
+    public void testPutshortArrayintint() {
+        buf.clear();
+        short array[] = new short[buf.capacity()];
+        try {
+            buf.put(new short[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, array.length + 1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        buf.put(array, array.length, 0);
+        assertEquals(buf.position(), 0);
+        try {
+            buf.put(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put((short[])null, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 2, array.length);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        assertEquals(buf.position(), 0);
+
+        loadTestData2(array, 0, array.length);
+        ShortBuffer ret = buf.put(array, 0, array.length);
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(buf, array, 0, array.length);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.ShortBuffer put(java.nio.ShortBuffer)
+     */
+    public void testPutShortBuffer() {
+        ShortBuffer other = ShortBuffer.allocate(buf.capacity());
+        try {
+            buf.put(buf);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            buf.put(ShortBuffer.allocate(buf.capacity() + 1));
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (BufferOverflowException e) {
+            // expected
+        }
+        try {
+            buf.flip();
+            buf.put((ShortBuffer)null);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        loadTestData2(other);
+        other.clear();
+        buf.clear();
+        ShortBuffer ret = buf.put(other);
+        assertEquals(other.position(), other.capacity());
+        assertEquals(buf.position(), buf.capacity());
+        assertContentEquals(other, buf);
+        assertSame(ret, buf);
+    }
+
+    /*
+     * Class under test for java.nio.ShortBuffer put(int, short)
+     */
+    public void testPutintshort() {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.position(), 0);
+            ShortBuffer ret = buf.put(i, (short) i);
+            assertEquals(buf.get(i), (short) i);
+            assertSame(ret, buf);
+        }
+        try {
+            buf.put(-1, (short) 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            buf.put(buf.limit(), (short) 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+    }
+
+    public void testSlice() {
+        assertTrue(buf.capacity() > 5);
+        buf.position(1);
+        buf.limit(buf.capacity() - 1);
+
+        ShortBuffer slice = buf.slice();
+        assertEquals(buf.isReadOnly(), slice.isReadOnly());
+        assertEquals(buf.isDirect(), slice.isDirect());
+        assertEquals(buf.order(), slice.order());
+        assertEquals(slice.position(), 0);
+        assertEquals(slice.limit(), buf.remaining());
+        assertEquals(slice.capacity(), buf.remaining());
+        try {
+            slice.reset();
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (InvalidMarkException e) {
+            // expected
+        }
+
+        // slice share the same content with buf
+        if (!slice.isReadOnly()) {
+            loadTestData1(slice);
+            assertContentLikeTestData1(buf, 1, (short) 0, slice.capacity());
+            buf.put(2, (short) 500);
+            assertEquals(slice.get(1), 500);
+        }
+    }
+
+    public void testToString() {
+        String str = buf.toString();
+        assertTrue(str.indexOf("Short") >= 0 || str.indexOf("short") >= 0);
+        assertTrue(str.indexOf("" + buf.position()) >= 0);
+        assertTrue(str.indexOf("" + buf.limit()) >= 0);
+        assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+    }
+
+    void loadTestData1(short array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (short) i;
+        }
+    }
+
+    void loadTestData2(short array[], int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            array[offset + i] = (short) (length - i);
+        }
+    }
+
+    void loadTestData1(ShortBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (short) i);
+        }
+    }
+
+    void loadTestData2(ShortBuffer buf) {
+        buf.clear();
+        for (int i = 0; i < buf.capacity(); i++) {
+            buf.put(i, (short) (buf.capacity() - i));
+        }
+    }
+
+    void assertContentEquals(ShortBuffer buf, short array[],
+            int offset, int length) {
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(i), array[offset + i]);
+        }
+    }
+
+    void assertContentEquals(ShortBuffer buf, ShortBuffer other) {
+        assertEquals(buf.capacity(), other.capacity());
+        for (int i = 0; i < buf.capacity(); i++) {
+            assertEquals(buf.get(i), other.get(i));
+        }
+    }
+
+    void assertContentLikeTestData1(ShortBuffer buf,
+            int startIndex, short startValue, int length) {
+        short value = startValue;
+        for (int i = 0; i < length; i++) {
+            assertEquals(buf.get(startIndex + i), value);
+            value = (short) (value + 1);
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceDirectByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceDirectByteBufferTest.java
new file mode 100644
index 0000000..541cde0
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceDirectByteBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class SliceDirectByteBufferTest extends DirectByteBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf.position(1).limit(BUFFER_LENGTH-1);
+        buf = buf.slice();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceHeapByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceHeapByteBufferTest.java
new file mode 100644
index 0000000..9f9f7aa
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceHeapByteBufferTest.java
@@ -0,0 +1,33 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class SliceHeapByteBufferTest extends HeapByteBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf.position(1).limit(BUFFER_LENGTH-1);
+        buf = buf.slice();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceWrappedByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceWrappedByteBufferTest.java
new file mode 100644
index 0000000..f1ddfb9
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceWrappedByteBufferTest.java
@@ -0,0 +1,33 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class SliceWrappedByteBufferTest extends WrappedByteBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf.position(1).limit(BUFFER_LENGTH-1);
+        buf = buf.slice();
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedByteBufferTest.java
new file mode 100644
index 0000000..6460d2e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedByteBufferTest.java
@@ -0,0 +1,97 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+
+public class WrappedByteBufferTest extends ByteBufferTest {
+    
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = ByteBuffer.wrap(new byte[BUFFER_LENGTH]);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        buf = null;
+        baseBuf = null;
+    }
+    
+    /**
+     * @tests java.nio.ByteBuffer#allocate(byte[],int,int)
+     * 
+     */
+    public void testWrappedByteBuffer_IllegalArg() {
+        byte array[] = new byte[BUFFER_LENGTH];
+        try {
+            ByteBuffer.wrap(array, -1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ByteBuffer.wrap(array, BUFFER_LENGTH + 1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ByteBuffer.wrap(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ByteBuffer.wrap(array, 0, BUFFER_LENGTH + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ByteBuffer.wrap(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ByteBuffer.wrap(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ByteBuffer.wrap((byte[])null, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+    
+    public void testIsDirect() {
+        assertFalse(buf.isDirect());
+    }
+
+    public void testHasArray() {
+        assertTrue(buf.hasArray());
+    }
+
+    public void testIsReadOnly() {
+        assertFalse(buf.isReadOnly());
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest1.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest1.java
new file mode 100644
index 0000000..9181a77
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest1.java
@@ -0,0 +1,84 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+public class WrappedCharBufferTest1 extends CharBufferTest {
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = CharBuffer.wrap(new char[BUFFER_LENGTH]);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        baseBuf = null;
+        buf = null;
+    }
+
+    /**
+     * @tests java.nio.CharBuffer#allocate(char[],int,int)
+     * 
+     */
+    public void testWrappedCharBuffer_IllegalArg() {
+        char array[] = new char[BUFFER_LENGTH];
+        try {
+            CharBuffer.wrap(array, -1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            CharBuffer.wrap(array, BUFFER_LENGTH + 1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            CharBuffer.wrap(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            CharBuffer.wrap(array, 0, BUFFER_LENGTH + 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            CharBuffer.wrap(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            CharBuffer.wrap(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            CharBuffer.wrap((char[])null, -1, 0);
+            fail("Should throw NPE"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest2.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest2.java
new file mode 100644
index 0000000..5fa9335
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest2.java
@@ -0,0 +1,128 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.CharBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class WrappedCharBufferTest2 extends ReadOnlyCharBufferTest {
+    protected static final String TEST_STRING = "123456789abcdef12345";
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = CharBuffer.wrap(TEST_STRING);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        baseBuf = null;
+        buf = null;
+    }
+
+    public void testWrappedCharSequence_IllegalArg() {
+        String str = TEST_STRING;
+        try {
+            CharBuffer.wrap(str, -1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            CharBuffer.wrap(str, 21, 21);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            CharBuffer.wrap(str, 2, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            CharBuffer.wrap(str, 0, 21);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            CharBuffer.wrap((String)null, -1, 21);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+    
+    public void testArray() {
+        try {
+            buf.array();
+            fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+        } catch (UnsupportedOperationException e) {
+        }
+    }
+    
+    public void testPutcharArrayintint() {
+        char array[] = new char[1];
+        try {
+            buf.put(array, 0, array.length);
+            fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException e) {
+            // expected
+        }
+        try {
+            buf.put((char[]) null, 0, 1);
+            fail("Should throw NullPointerException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException expected) {
+        } catch (NullPointerException expected) {
+        }
+        try {
+            buf.put(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+            fail("Should throw BufferOverflowException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException expected) {
+        } catch (BufferOverflowException expected) {
+        }
+        try {
+            buf.put(array, -1, array.length);
+            fail("Should throw IndexOutOfBoundsException"); //$NON-NLS-1$
+        } catch (ReadOnlyBufferException expected) {
+        } catch (IndexOutOfBoundsException expected) {
+        }
+    }
+
+    public void testPutCharBuffer() {
+        CharBuffer other = CharBuffer.allocate(1);
+        try {
+            buf.put(other);
+            fail();
+        } catch (ReadOnlyBufferException expected) {
+        }
+        try {
+            buf.put((CharBuffer) null);
+            fail();
+        } catch (ReadOnlyBufferException expected) {
+        } catch (NullPointerException expected) {
+        }
+        try {
+            buf.put(buf);
+            fail();
+        } catch (ReadOnlyBufferException expected) {
+        } catch (IllegalArgumentException expected) {
+        }
+    }    
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedDoubleBufferTest.java
new file mode 100644
index 0000000..f970849
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedDoubleBufferTest.java
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class WrappedDoubleBufferTest extends DoubleBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = DoubleBuffer.wrap(new double[BUFFER_LENGTH]);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        baseBuf = null;
+        buf = null;
+    }
+
+    /**
+     * @tests java.nio.CharBuffer#allocate(char[],int,int)
+     * 
+     */
+    public void testWrappedDoubleuffer_IllegalArg() {
+    	double array[] = new double[20];
+        try {
+            DoubleBuffer.wrap(array, -1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            DoubleBuffer.wrap(array, 21, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            DoubleBuffer.wrap(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            DoubleBuffer.wrap(array, 0, 21);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            DoubleBuffer.wrap(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            DoubleBuffer.wrap(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            DoubleBuffer.wrap((double[])null, -1, 0);
+            fail("Should throw NPE"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+        }
+
+        DoubleBuffer buf = DoubleBuffer.wrap(array, 2, 16);
+        assertEquals(buf.position(), 2);
+        assertEquals(buf.limit(), 18);
+        assertEquals(buf.capacity(), 20);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedFloatBufferTest.java
new file mode 100644
index 0000000..43b13c3
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedFloatBufferTest.java
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class WrappedFloatBufferTest extends FloatBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = FloatBuffer.wrap(new float[BUFFER_LENGTH]);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        baseBuf = null;
+        buf = null;
+    }
+
+    /**
+     * @tests java.nio.CharBuffer#allocate(char[],int,int)
+     * 
+     */
+    public void testWrappedFloatBuffer_IllegalArg() {
+        float array[] = new float[20];
+        try {
+            FloatBuffer.wrap(array, -1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            FloatBuffer.wrap(array, 21, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            FloatBuffer.wrap(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            FloatBuffer.wrap(array, 0, 21);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            FloatBuffer.wrap(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            FloatBuffer.wrap(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            FloatBuffer.wrap((float[])null, -1, 0);
+            fail("Should throw NPE"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+        }
+
+        FloatBuffer buf = FloatBuffer.wrap(array, 2, 16);
+        assertEquals(buf.position(), 2);
+        assertEquals(buf.limit(), 18);
+        assertEquals(buf.capacity(), 20);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedIntBufferTest.java
new file mode 100644
index 0000000..383e964
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedIntBufferTest.java
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class WrappedIntBufferTest extends IntBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = IntBuffer.wrap(new int[BUFFER_LENGTH]);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        baseBuf = null;
+        buf = null;
+    }
+
+    /**
+     * @tests java.nio.CharBuffer#allocate(char[],int,int)
+     * 
+     */
+    public void testWrappedIntBuffer_IllegalArg() {
+        int array[] = new int[20];
+        try {
+            IntBuffer.wrap(array, -1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            IntBuffer.wrap(array, 21, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            IntBuffer.wrap(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            IntBuffer.wrap(array, 0, 21);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            IntBuffer.wrap(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            IntBuffer.wrap(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            IntBuffer.wrap((int[])null, -1, 0);
+            fail("Should throw NPE"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+        }
+
+        IntBuffer buf = IntBuffer.wrap(array, 2, 16);
+        assertEquals(buf.position(), 2);
+        assertEquals(buf.limit(), 18);
+        assertEquals(buf.capacity(), 20);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedLongBufferTest.java
new file mode 100644
index 0000000..581c912
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedLongBufferTest.java
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class WrappedLongBufferTest extends LongBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = LongBuffer.wrap(new long[BUFFER_LENGTH]);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        baseBuf = null;
+        buf = null;
+    }
+
+    /**
+     * @tests java.nio.CharBuffer#allocate(char[],int,int)
+     * 
+     */
+    public void testWrappedLongBuffer_IllegalArg() {
+        long array[] = new long[20];
+        try {
+            LongBuffer.wrap(array, -1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            LongBuffer.wrap(array, 21, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            LongBuffer.wrap(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            LongBuffer.wrap(array, 0, 21);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            LongBuffer.wrap(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            LongBuffer.wrap(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            LongBuffer.wrap((long[])null, -1, 0);
+            fail("Should throw NPE"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+        }
+
+        LongBuffer buf = LongBuffer.wrap(array, 2, 16);
+        assertEquals(buf.position(), 2);
+        assertEquals(buf.limit(), 18);
+        assertEquals(buf.capacity(), 20);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedShortBufferTest.java
new file mode 100644
index 0000000..9c6f781
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedShortBufferTest.java
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class WrappedShortBufferTest extends ShortBufferTest {
+    protected void setUp() throws Exception {
+        super.setUp();
+        buf = ShortBuffer.wrap(new short[BUFFER_LENGTH]);
+        loadTestData1(buf);
+        baseBuf = buf;
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        baseBuf = null;
+        buf = null;
+    }
+
+    /**
+     * @tests java.nio.CharBuffer#allocate(char[],int,int)
+     * 
+     */
+    public void testWrappedShortBuffer_IllegalArg() {
+        short array[] = new short[20];
+        try {
+            ShortBuffer.wrap(array, -1, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ShortBuffer.wrap(array, 21, 0);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ShortBuffer.wrap(array, 0, -1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ShortBuffer.wrap(array, 0, 21);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ShortBuffer.wrap(array, Integer.MAX_VALUE, 1);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ShortBuffer.wrap(array, 1, Integer.MAX_VALUE);
+            fail("Should throw Exception"); //$NON-NLS-1$
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+        try {
+            ShortBuffer.wrap((short[])null, -1, 0);
+            fail("Should throw NPE"); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+        }
+
+        ShortBuffer buf = ShortBuffer.wrap(array, 2, 16);
+        assertEquals(buf.position(), 2);
+        assertEquals(buf.limit(), 18);
+        assertEquals(buf.capacity(), 20);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java
new file mode 100644
index 0000000..ac820a4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.AlreadyConnectedException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for AlreadyConnectedException
+ */
+public class AlreadyConnectedExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.AlreadyConnectedException#AlreadyConnectedException()}
+     */
+    public void test_Constructor() {
+        AlreadyConnectedException e = new AlreadyConnectedException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new AlreadyConnectedException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new AlreadyConnectedException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java
new file mode 100644
index 0000000..123eb1f
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.AsynchronousCloseException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for AsynchronousCloseException
+ */
+public class AsynchronousCloseExceptionTest extends TestCase {
+
+    /**
+     * @tests {@link java.nio.channels.AsynchronousCloseException#AsynchronousCloseException()}
+     */
+    public void test_Constructor() {
+        AsynchronousCloseException e = new AsynchronousCloseException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+    
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new AsynchronousCloseException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new AsynchronousCloseException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java
new file mode 100644
index 0000000..7a73322
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.CancelledKeyException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for CancelledKeyException
+ */
+public class CancelledKeyExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.CancelledKeyException#CancelledKeyException()}
+     */
+    public void test_Constructor() {
+        CancelledKeyException e = new CancelledKeyException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new CancelledKeyException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new CancelledKeyException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ChannelsTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ChannelsTest.java
new file mode 100644
index 0000000..4223fb8
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ChannelsTest.java
@@ -0,0 +1,622 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+
+import tests.support.Support_PortManager;
+
+import junit.framework.TestCase;
+
+/**
+ * Note: the test case uses a temp text file named "test" which contains 31
+ * characters : "P@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]"
+ * 
+ */
+
+public class ChannelsTest extends TestCase {
+    private static final String CODE_SET = "GB2312"; //$NON-NLS-1$
+
+    private static final String BAD_CODE_SET = "GB2313"; //$NON-NLS-1$
+
+    private FileInputStream fins;
+
+    private FileOutputStream fouts;
+
+    private final int writebufSize = 60;
+
+    private final int testNum = 10;
+
+    private final int fileSize = 31;// the file size
+    
+    private File tmpFile;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        // Make the test file same in every test
+        tmpFile = File.createTempFile("test","tmp");
+        tmpFile.deleteOnExit();
+        this.writeFileSame();
+    }
+
+    protected void tearDown() throws Exception {
+        if (null != this.fins) {
+            this.fins.close();
+            this.fins = null;
+        }
+        if (null != this.fouts) {
+            this.fouts.close();
+            this.fouts = null;
+        }
+
+        tmpFile.delete();
+        super.tearDown();
+
+    }
+
+    private void writeFileSame() throws IOException {
+        this.fouts = new FileOutputStream(tmpFile);
+        byte[] bit = new byte[1];
+        bit[0] = 80;
+        this.fouts.write(bit);
+        this.fouts.flush();
+        String writebuf = ""; //$NON-NLS-1$
+        for (int val = 0; val < this.writebufSize / 2; val++) {
+            writebuf = writebuf + ((char) (val + 64));
+        }
+        this.fouts.write(writebuf.getBytes());
+    }
+
+    /*
+     * This private method is to assert if the file size is the same as the
+     * compare Number in the test
+     */
+    private void assertFileSizeSame(File fileToTest, int compareNumber)
+            throws IOException {
+        FileInputStream file = new FileInputStream(fileToTest);
+        assertEquals(file.available(), compareNumber);
+        file.close();
+    }
+
+    // test if new Channel to input is null
+    public void testNewChannelInputStream_InputNull() throws IOException {
+        ByteBuffer byteBuf = ByteBuffer.allocate(this.testNum);
+        this.fins = null;
+        int readres = this.testNum;
+        try {
+            ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+            assertNotNull(rbChannel);
+            readres = rbChannel.read(byteBuf);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        assertEquals(this.testNum, readres);
+    }
+
+    // test if buffer to read is null
+    public void testNewChannelInputStream_BufferNull() throws IOException {
+        ByteBuffer byteBuf = ByteBuffer.allocate(this.testNum);
+        int readres = this.testNum;
+        this.fins = new FileInputStream(tmpFile);
+        ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+        assertNotNull(rbChannel);
+        try {
+            readres = rbChannel.read(null);
+            fail();
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(this.testNum, readres);
+        readres = 0;
+        try {
+            readres = rbChannel.read(byteBuf);
+        } catch (NullPointerException e) {
+            fail();
+        }
+        assertEquals(this.testNum, readres);
+    }
+
+    /*
+     * Test method for 'java.nio.channels.Channels.NewChannel'
+     */
+    public void testNewChannelInputStream() throws IOException {
+        int bufSize = 10;
+        int readres = 0;
+        byte[] byteArray = new byte[bufSize];
+        ByteBuffer byteBuf = ByteBuffer.allocate(bufSize);
+        this.fins = new FileInputStream(tmpFile);
+        readres = this.fins.read(byteArray);
+
+        assertEquals(bufSize, readres);
+        assertFalse(0 == this.fins.available());
+
+        ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+        // fins still reads.
+        assertFalse(0 == this.fins.available());
+        readres = this.fins.read(byteArray);
+        assertEquals(bufSize, readres);
+
+        // rbChannel also reads.
+        assertNotNull(rbChannel);
+        readres = rbChannel.read(byteBuf);
+
+        assertEquals(bufSize, readres);
+        InputStream ins = Channels.newInputStream(rbChannel);
+        assertNotNull(ins);
+        assertEquals(0, ins.available());
+    }
+
+    // test if fout to change is null
+    public void testNewChannelOutputStream_inputNull() throws IOException {
+        int writeres = this.testNum;
+        ByteBuffer writebuf = ByteBuffer.allocate(this.writebufSize);
+        for (int val = 0; val < this.writebufSize / 2; val++) {
+            writebuf.putChar((char) (val + 64));
+        }
+        this.fouts = null;
+        try {
+            WritableByteChannel rbChannel = Channels.newChannel(this.fouts);
+            writeres = rbChannel.write(writebuf);
+            assertEquals(0, writeres);
+
+            writebuf.flip();
+            writeres = rbChannel.write(writebuf);
+            fail("Should throw NPE.");
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    // test if write buf is null
+    public void testNewChannelOutputStream_BufNull() throws IOException {
+        int writeres = this.testNum;
+        ByteBuffer writebuf = null;
+        try {
+            this.fouts = new FileOutputStream(tmpFile);
+        } catch (FileNotFoundException e) {
+            fail();
+        }
+
+        WritableByteChannel rbChannel = Channels.newChannel(this.fouts);
+        try {
+            writeres = rbChannel.write(writebuf);
+            fail();
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(this.testNum, writeres);
+    }
+
+    /*
+     * Test method for 'java.nio.channels.Channels.NewChannel(OutputStream)'
+     */
+    public void testNewChannelOutputStream() throws IOException {
+        int writeNum = 0;
+        ByteBuffer writebuf = ByteBuffer.allocateDirect(this.writebufSize);
+        for (int val = 0; val < this.writebufSize / 2; val++) {
+            writebuf.putChar((char) (val + 64));
+        }
+        this.fouts = new FileOutputStream(tmpFile);
+        WritableByteChannel testChannel = this.fouts.getChannel();
+        WritableByteChannel rbChannel = Channels.newChannel(this.fouts);
+
+        assertTrue(testChannel.isOpen());
+        assertTrue(rbChannel.isOpen());
+
+        byte[] bit = new byte[1];
+        bit[0] = 80;
+        this.fouts.write(bit);
+        this.fouts.flush();
+        this.fins = new FileInputStream(tmpFile);
+        assertEquals(this.fins.available(), 1);
+        this.fins.close();
+
+        writeNum = rbChannel.write(writebuf);
+        // write success ,but output null
+        assertEquals(0, writeNum);
+        // close of fouts does not affect on channel
+        this.fouts.close();
+        writeNum = rbChannel.write(writebuf);
+        assertEquals(0, writeNum);
+        try {
+            writeNum = testChannel.write(writebuf);
+            fail();
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+        assertEquals(0, writeNum);
+        // close of rbchannel does affect on testchannel(same channel)
+        rbChannel.close();
+        try {
+            writeNum = testChannel.write(writebuf);
+            fail();
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testNewInputStreamReadableByteChannel_InputNull()
+            throws Exception {
+        byte[] readbuf = new byte[this.testNum];
+        this.fins = new FileInputStream(tmpFile);
+        ReadableByteChannel readbc = this.fins.getChannel();
+        assertEquals(this.fileSize, this.fins.available());
+        assertTrue(readbc.isOpen());
+
+        try {
+            InputStream testins = Channels.newInputStream(null);
+            assertNotNull(testins);
+            testins.read(readbuf);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void testNewInputStreamReadableByteChannel() throws Exception {
+        ByteBuffer readbcbuf = ByteBuffer.allocateDirect(this.testNum);
+        byte[] readbuf = new byte[this.testNum];
+        this.fins = new FileInputStream(tmpFile);
+        ReadableByteChannel readbc = this.fins.getChannel();
+        assertEquals(this.fileSize, this.fins.available());
+        assertTrue(readbc.isOpen());
+        InputStream testins = Channels.newInputStream(readbc);
+        // read in testins and fins use the same pointer
+        testins.read(readbuf);
+        assertEquals(this.fins.available(), this.fileSize - this.testNum);
+        int readNum = readbc.read(readbcbuf);
+        assertEquals(readNum, this.testNum);
+        assertEquals(this.fins.available(), this.fileSize - this.testNum * 2);
+        testins.read(readbuf);
+        assertEquals(this.fins.available(), this.fileSize - this.testNum * 3);
+        // readbc.close() affect testins
+        readbc.close();
+        assertFalse(readbc.isOpen());
+        try {
+            testins.read(readbuf);
+            fail();
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testNewOutputStreamWritableByteChannel_InputNull()
+            throws Exception {
+        byte[] writebuf = new byte[this.testNum];
+        try {
+            OutputStream testouts = Channels.newOutputStream(null);
+            assertNotNull(testouts);
+            testouts.write(writebuf);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            WritableByteChannel writebc = Channels.newChannel((OutputStream) null);
+            assertTrue(writebc.isOpen());
+            OutputStream testoutputS = Channels.newOutputStream(writebc);
+            testoutputS.write(writebuf);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void testNewOutputStreamWritableByteChannel() throws Exception {
+        byte[] writebuf = new byte[this.testNum];
+        ByteBuffer writebcbuf = ByteBuffer.allocateDirect(this.testNum);
+        this.fouts = new FileOutputStream(tmpFile);
+        WritableByteChannel writebc = this.fouts.getChannel();
+
+        assertTrue(writebc.isOpen());
+        OutputStream testouts = Channels.newOutputStream(writebc);
+
+        // read in testins and fins use the same pointer
+        testouts.write(writebuf);
+        this.assertFileSizeSame(tmpFile, this.testNum);
+        writebc.write(writebcbuf);
+        this.assertFileSizeSame(tmpFile, this.testNum * 2);
+        testouts.write(writebuf);
+        this.assertFileSizeSame(tmpFile, this.testNum * 3);
+        // readbc.close() affect testins
+        writebc.close();
+        assertFalse(writebc.isOpen());
+        try {
+            testouts.write(writebuf);
+            fail();
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testnewReaderCharsetError() throws Exception {
+        this.fins = new FileInputStream(tmpFile);
+
+        ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+        try {
+            Channels.newReader(rbChannel, Charset.forName(BAD_CODE_SET)
+                    .newDecoder(), //$NON-NLS-1$
+                    -1);
+            fail();
+        } catch (UnsupportedCharsetException e) {
+            // correct
+        }
+    }
+
+    public void testnewWriterCharsetError() throws Exception {
+        this.fouts = new FileOutputStream(tmpFile);
+        WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+        try {
+            Channels.newWriter(wbChannel, Charset.forName(BAD_CODE_SET)
+                    .newEncoder(), -1);
+            fail();
+        } catch (UnsupportedCharsetException e) {
+            // correct
+        }
+    }
+
+    /*
+     * Test method for
+     * 'java.nio.channels.Channels.newReader(ReadableByteChannel, String)'
+     */
+    public void testNewReaderReadableByteChannelString_InputNull()
+            throws IOException {
+        int bufSize = this.testNum;
+        int readres = 0;
+        CharBuffer charBuf = CharBuffer.allocate(bufSize);
+        this.fins = new FileInputStream(tmpFile);
+        // channel null
+        Reader testReader;
+        try {
+            testReader = Channels.newReader(null, Charset.forName(CODE_SET).newDecoder(), -1);
+            assertNotNull(testReader);
+            assertFalse(testReader.ready());
+            readres = testReader.read((CharBuffer) null);
+            fail();
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(0, readres);
+
+        this.fins = null;
+        // channel with null inputs
+        try {
+            ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+            testReader = Channels.newReader(rbChannel, Charset.forName(CODE_SET).newDecoder(), -1);
+            assertNotNull(testReader);
+            assertFalse(testReader.ready());
+            readres = testReader.read(charBuf);
+            fail();
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    /*
+     * Test method for
+     * 'java.nio.channels.Channels.newReader(ReadableByteChannel, String)'
+     */
+    public void testNewReaderReadableByteChannelString_internalBufferZero()
+            throws IOException {
+        int bufSize = this.testNum;
+        int readres = 0;
+        CharBuffer charBuf = CharBuffer.allocate(bufSize);
+        this.fins = new FileInputStream(tmpFile);
+        // channel null
+        Reader testReader;
+        try {
+            testReader = Channels.newReader(null, Charset.forName(CODE_SET).newDecoder(), 0);
+            assertNotNull(testReader);
+            assertFalse(testReader.ready());
+            readres = testReader.read((CharBuffer) null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        assertEquals(0, readres);
+
+        this.fins = null;
+        // channel with null inputs
+        try {
+            ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+            testReader = Channels.newReader(rbChannel, Charset.forName(CODE_SET).newDecoder(), -1);
+            assertNotNull(testReader);
+            assertFalse(testReader.ready());
+            readres = testReader.read(charBuf);
+            fail();
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    /*
+     * Test method for
+     * 'java.nio.channels.Channels.newReader(ReadableByteChannel, String)'
+     */
+    public void testNewReaderReadableByteChannelString() throws IOException {
+        int bufSize = this.testNum;
+        int readres = 0;
+        CharBuffer charBuf = CharBuffer.allocate(bufSize);
+        this.fins = new FileInputStream(tmpFile);
+        ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+        Reader testReader = Channels.newReader(rbChannel, Charset.forName(
+                CODE_SET).newDecoder(), //$NON-NLS-1$
+                -1);
+        Reader testReader_s = Channels.newReader(rbChannel, CODE_SET); //$NON-NLS-1$
+
+        assertEquals(this.fileSize, this.fins.available());
+        // not ready...
+        assertFalse(testReader.ready());
+        assertFalse(testReader_s.ready());
+        // still reads
+        readres = testReader.read(charBuf);
+        assertEquals(bufSize, readres);
+        assertEquals(0, this.fins.available());
+
+        try {
+            readres = testReader.read((CharBuffer) null);
+            fail();
+        } catch (NullPointerException e) {
+            // correct
+        }
+
+        readres = testReader_s.read(charBuf);
+        assertEquals(0, readres);
+        assertTrue(testReader.ready());
+        assertFalse(testReader_s.ready());
+    }
+
+    /*
+     * Zero-Buffer
+     */
+    public void testNewWriterWritableByteChannelString_internalBufZero()
+            throws IOException {
+
+        String writebuf = ""; //$NON-NLS-1$
+        for (int val = 0; val < this.writebufSize / 2; val++) {
+            writebuf = writebuf + ((char) (val + 64));
+        }
+        // null channel
+        try {
+            Writer testWriter = Channels.newWriter(null, Charset.forName(CODE_SET).newEncoder(), -1);
+        } catch (NullPointerException expected) {
+        }
+
+        // channel with null input
+        this.fouts = null;
+        try {
+            WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    /*
+     * this test cannot be passed when buffer set to 0!
+     */
+    public void testNewWriterWritableByteChannelString_InputNull()
+            throws IOException {
+        this.fouts = new FileOutputStream(tmpFile);
+        WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+        Writer testWriter = Channels.newWriter(wbChannel, Charset.forName(
+                CODE_SET).newEncoder(), //$NON-NLS-1$
+                1);
+
+        String writebuf = ""; //$NON-NLS-1$
+        for (int val = 0; val < this.writebufSize / 2; val++) {
+            writebuf = writebuf + ((char) (val + 64));
+        }
+        // can write to buffer
+        testWriter.write(writebuf);
+        testWriter.flush();
+        testWriter.close();
+
+    }
+
+    /*
+     * Test method for
+     * 'java.nio.channels.Channels.newWriter(WritableByteChannel, String)'
+     */
+    public void testNewWriterWritableByteChannelString() throws IOException {
+        this.fouts = new FileOutputStream(tmpFile);
+        WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+        Writer testWriter = Channels.newWriter(wbChannel, CODE_SET); //$NON-NLS-1$
+        Writer testWriter_s = Channels.newWriter(wbChannel, Charset.forName(
+                CODE_SET).newEncoder(), //$NON-NLS-1$
+                -1);
+
+        String writebuf = ""; //$NON-NLS-1$
+        for (int val = 0; val < this.writebufSize / 2; val++) {
+            writebuf = writebuf + ((char) (val + 64));
+        }
+        byte[] bit = new byte[1];
+        bit[0] = 80;
+        this.fouts.write(bit);
+        this.assertFileSizeSame(tmpFile, 1);
+
+        // writer continues to write after '1',what the fouts write
+        testWriter.write(writebuf);
+        testWriter.flush();
+        this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+        // testwriter_s does not know if testwrite writes
+        testWriter_s.write(writebuf);
+        testWriter.flush();
+        this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+        // testwriter_s even does not know if himself writes?
+        testWriter_s.write(writebuf);
+        testWriter.flush();
+        this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+
+        // close the fouts, no longer writable for testWriter
+        for (int val = 0; val < this.writebufSize; val++) {
+            writebuf = writebuf + ((char) (val + 64));
+        }
+        this.fouts.close();
+        testWriter_s.write(writebuf);
+        testWriter.flush();
+        this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+    }
+	
+    /**
+	 * @tests java.nio.channels.Channels#newReader(ReadableByteChannel channel,
+	 *        String charsetName)
+	 */
+	public void test_newReader_LReadableByteChannel_LString()
+			throws IOException {
+		InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
+				Support_PortManager.getNextPort());
+		ServerSocketChannel ssc = ServerSocketChannel.open();
+		ssc.socket().bind(localAddr);
+
+		SocketChannel sc = SocketChannel.open();
+		sc.connect(localAddr);
+		sc.configureBlocking(false);
+		assertFalse(sc.isBlocking());
+
+		ssc.accept().close();
+		ssc.close();
+		assertFalse(sc.isBlocking());
+
+		Reader reader = Channels.newReader(sc, "UTF16");
+		try {
+			int i = reader.read();
+			fail("should throw IllegalBlockingModeException");
+		} catch (IllegalBlockingModeException expected) {
+		}
+
+		try {
+			Channels.newInputStream(sc).read();
+			fail("should throw IllegalBlockingModeException");
+		} catch (IllegalBlockingModeException expected) {
+		}
+
+		sc.close();
+	}
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java
new file mode 100644
index 0000000..aba37ec
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java
@@ -0,0 +1,53 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.ClosedByInterruptException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ClosedByInterruptException
+ */
+public class ClosedByInterruptExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.ClosedByInterruptException#ClosedByInterruptException()}
+     */
+    public void test_Constructor() {
+        ClosedByInterruptException e = new ClosedByInterruptException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new ClosedByInterruptException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new ClosedByInterruptException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java
new file mode 100644
index 0000000..3ba322f
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.ClosedChannelException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ClosedChannelException
+ */
+public class ClosedChannelExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.ClosedChannelException#ClosedChannelException()}
+     */
+    public void test_Constructor() {
+        ClosedChannelException e = new ClosedChannelException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new ClosedChannelException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new ClosedChannelException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java
new file mode 100644
index 0000000..745d697
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.ClosedSelectorException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ClosedSelectorException
+ */
+public class ClosedSelectorExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.ClosedSelectorException#ClosedSelectorException()}
+     */
+    public void test_Constructor() {
+        ClosedSelectorException e = new ClosedSelectorException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new ClosedSelectorException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new ClosedSelectorException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java
new file mode 100644
index 0000000..0e909ba
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.ConnectionPendingException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ConnectionPendingException
+ */
+public class ConnectionPendingExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.ConnectionPendingException#ConnectionPendingException()}
+     */
+    public void test_Constructor() {
+        ConnectionPendingException e = new ConnectionPendingException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new ConnectionPendingException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new ConnectionPendingException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
new file mode 100644
index 0000000..cff718e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
@@ -0,0 +1,2557 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+import java.security.Permission;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/**
+ * Test for DatagramChannel
+ *
+ */
+public class DatagramChannelTest extends TestCase {
+
+    private static final int CAPACITY_NORMAL = 200;
+
+    private static final int CAPACITY_1KB = 1024;
+
+    private static final int CAPACITY_64KB = 65536;
+
+    private static final int CAPACITY_ZERO = 0;
+
+    private static final int CAPACITY_ONE = 1;
+
+    private static final int TIME_UNIT = 500;
+
+    private InetSocketAddress localAddr1;
+
+    private InetSocketAddress localAddr2;
+
+    private DatagramChannel channel1;
+
+    private DatagramChannel channel2;
+
+    private DatagramSocket datagramSocket1;
+
+    private DatagramSocket datagramSocket2;
+
+    // The port to be used in test cases.
+    private int testPort;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.channel1 = DatagramChannel.open();
+        this.channel2 = DatagramChannel.open();
+        int[] ports = Support_PortManager.getNextPortsForUDP(5);
+        this.localAddr1 = new InetSocketAddress("127.0.0.1", ports[0]);
+        this.localAddr2 = new InetSocketAddress("127.0.0.1", ports[1]);
+        this.datagramSocket1 = new DatagramSocket(ports[2]);
+        this.datagramSocket2 = new DatagramSocket(ports[3]);
+        testPort = ports[4];
+    }
+
+    protected void tearDown() throws Exception {
+        if (null != this.channel1) {
+            try {
+                this.channel1.close();
+            } catch (Exception e) {
+                //ignore
+            }
+        }
+        if (null != this.channel2) {
+            try {
+                this.channel2.close();
+            } catch (Exception e) {
+                //ignore
+            }
+        }
+        if (null != this.datagramSocket1) {
+            try {
+                this.datagramSocket1.close();
+            } catch (Exception e) {
+                //ignore
+            }
+        }
+        if (null != this.datagramSocket2) {
+            try {
+                this.datagramSocket2.close();
+            } catch (Exception e) {
+                //ignore
+            }
+        }
+        localAddr1 = null;
+        localAddr2 = null;
+        super.tearDown();
+    }
+
+    // -------------------------------------------------------------------
+    // Test for methods in abstract class.
+    // -------------------------------------------------------------------
+    /*
+     * Test method for 'java.nio.channels.DatagramChannel.validOps()'
+     */
+    public void testValidOps() {
+        MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+                .provider());
+        MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+        int val = this.channel1.validOps();
+        assertEquals(5, val);
+        assertEquals(val, testMock.validOps());
+        assertEquals(val, testMocknull.validOps());
+    }
+
+    /*
+     * Test method for 'java.nio.channels.DatagramChannel.open()'
+     */
+    public void testOpen() {
+        MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+                .provider());
+        MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+        assertNull(testMocknull.provider());
+        assertNotNull(testMock.provider());
+        assertEquals(this.channel1.provider(), testMock.provider());
+        assertEquals(5, testMock.validOps());
+    }
+
+    /*
+     * Test method for 'java.nio.channels.DatagramChannel.read(ByteBuffer)'
+     */
+    public void testReadByteBufferArray() throws IOException {
+        final int testNum = 0;
+        long readres = testNum;
+        MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+                .provider());
+        MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+        int bufSize = 10;
+        ByteBuffer[] readBuf = null;
+        try {
+            this.channel1.read(readBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            readres = testMock.read(readBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        readBuf = new ByteBuffer[bufSize];
+        try {
+            readres = this.channel1.read(readBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        readres = testMock.read(readBuf);
+        assertEquals(testNum, readres);
+        readres = testMocknull.read(readBuf);
+        assertEquals(testNum, readres);
+    }
+
+    /*
+     * Test method for 'java.nio.channels.DatagramChannel.read(ByteBuffer)'
+     */
+    public void testReadByteBufferArray_BufNull() throws IOException {
+        MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+                .provider());
+        MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+
+        ByteBuffer[] readBuf = null;
+        try {
+            this.channel1.read(readBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            testMock.read(readBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            testMocknull.read(readBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    /*
+     * Test method for 'java.nio.channels.DatagramChannel.write(ByteBuffer)'
+     */
+    public void testWriteByteBuffer() throws IOException {
+        MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+                .provider());
+        MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+        int bufSize = 10;
+        ByteBuffer[] readBuf = null;
+        try {
+            this.channel1.write(readBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            testMock.write(readBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        readBuf = new ByteBuffer[bufSize];
+        try {
+            this.channel1.write(readBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        long writeres = 0;
+        writeres = testMock.write(readBuf);
+
+        assertEquals(0, writeres);
+        writeres = testMocknull.write(readBuf);
+        assertEquals(0, writeres);
+    }
+
+    /*
+     * Test method for 'java.nio.channels.DatagramChannel.write(ByteBuffer)'
+     */
+    public void testWriteByteBuffer_Bufnull() throws IOException {
+        MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+                .provider());
+        MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+        ByteBuffer[] readBuf = null;
+        try {
+            this.channel1.write(readBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            testMock.write(readBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            testMocknull.write(readBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Test for socket()
+    // -------------------------------------------------------------------
+
+    /**
+     * Test method for 'DatagramChannelImpl.socket()'
+     *
+     * @throws SocketException
+     */
+    public void testSocket_BasicStatusBeforeConnect() throws SocketException {
+        assertFalse(this.channel1.isConnected());// not connected
+        DatagramSocket s1 = this.channel1.socket();
+        assertSocketBeforeConnect(s1);
+        DatagramSocket s2 = this.channel1.socket();
+        // same
+        assertSame(s1, s2);
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.socket()'
+     *
+     * @throws IOException
+     */
+    public void testSocket_Block_BasicStatusAfterConnect() throws IOException {
+        this.channel1.connect(localAddr1);
+        DatagramSocket s1 = this.channel1.socket();
+        assertSocketAfterConnect(s1);
+        DatagramSocket s2 = this.channel1.socket();
+        // same
+        assertSame(s1, s2);
+    }
+
+    public void testSocket_NonBlock_BasicStatusAfterConnect()
+            throws IOException {
+        this.channel1.connect(localAddr1);
+        this.channel1.configureBlocking(false);
+        DatagramSocket s1 = this.channel1.socket();
+        assertSocketAfterConnect(s1);
+        DatagramSocket s2 = this.channel1.socket();
+        // same
+        assertSame(s1, s2);
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.socket()'
+     *
+     * @throws IOException
+     */
+    public void testSocket_ActionsBeforeConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        DatagramSocket s = this.channel1.socket();
+        assertSocketActionBeforeConnect(s);
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.socket()'
+     *
+     * @throws IOException
+     */
+    public void testSocket_Block_ActionsAfterConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        this.channel1.connect(localAddr1);
+        DatagramSocket s = this.channel1.socket();
+        assertSocketActionAfterConnect(s);
+    }
+
+    public void testSocket_NonBlock_ActionsAfterConnect() throws IOException {
+        this.channel1.connect(localAddr1);
+        this.channel1.configureBlocking(false);
+        DatagramSocket s = this.channel1.socket();
+        assertSocketActionAfterConnect(s);
+    }
+
+    private void assertSocketBeforeConnect(DatagramSocket s)
+            throws SocketException {
+        assertFalse(s.isBound());
+        assertFalse(s.isClosed());
+        assertFalse(s.isConnected());
+        assertFalse(s.getBroadcast());
+        assertFalse(s.getReuseAddress());
+        assertNull(s.getInetAddress());
+        assertTrue(s.getLocalAddress().isAnyLocalAddress());
+        assertEquals(s.getLocalPort(), 0);
+        assertNull(s.getLocalSocketAddress());
+        assertEquals(s.getPort(), -1);
+        assertTrue(s.getReceiveBufferSize() >= 8192);
+        assertNull(s.getRemoteSocketAddress());
+        assertFalse(s.getReuseAddress());
+        assertTrue(s.getSendBufferSize() >= 8192);
+        assertEquals(s.getSoTimeout(), 0);
+        assertEquals(s.getTrafficClass(), 0);
+    }
+
+    private void assertSocketAfterConnect(DatagramSocket s)
+            throws SocketException {
+        assertTrue(s.isBound());
+        assertFalse(s.isClosed());
+        assertTrue(s.isConnected());
+        assertFalse(s.getBroadcast());
+        assertFalse(s.getReuseAddress());
+        assertSame(s.getInetAddress(), localAddr1.getAddress());
+        assertEquals(s.getLocalAddress(), localAddr1.getAddress());
+        assertNotNull(s.getLocalSocketAddress());
+        assertEquals(s.getPort(), localAddr1.getPort());
+        assertTrue(s.getReceiveBufferSize() >= 8192);
+        // not same , but equals
+        assertNotSame(s.getRemoteSocketAddress(), (SocketAddress) localAddr1);
+        assertEquals(s.getRemoteSocketAddress(), (SocketAddress) localAddr1);
+        assertFalse(s.getReuseAddress());
+        assertTrue(s.getSendBufferSize() >= 8192);
+        assertEquals(s.getSoTimeout(), 0);
+        assertEquals(s.getTrafficClass(), 0);
+    }
+
+    private void assertSocketActionBeforeConnect(DatagramSocket s)
+            throws IOException {
+        s.connect(localAddr2);
+        assertFalse(this.channel1.isConnected());
+        assertFalse(s.isConnected());
+
+        s.disconnect();
+        assertFalse(this.channel1.isConnected());
+        assertFalse(s.isConnected());
+
+        s.close();
+        assertTrue(s.isClosed());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    private void assertSocketActionAfterConnect(DatagramSocket s)
+            throws IOException {
+        assertEquals(s.getPort(), localAddr1.getPort());
+        s.connect(localAddr2);
+        assertTrue(this.channel1.isConnected());
+        assertTrue(s.isConnected());
+        // not changed
+        assertEquals(s.getPort(), localAddr1.getPort());
+
+        s.disconnect();
+        assertFalse(this.channel1.isConnected());
+        assertFalse(s.isConnected());
+
+        s.close();
+        assertTrue(s.isClosed());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    // -------------------------------------------------------------------
+    // Test for configureBlocking()
+    // -------------------------------------------------------------------
+
+    public void testConfigureBlocking_Read() throws Exception {
+        assertTrue(this.channel1.isBlocking());
+        ByteBuffer buf = ByteBuffer.allocate(CAPACITY_1KB);
+        new Thread() {
+            public void run() {
+                try {
+                    sleep(TIME_UNIT * 5);
+                    channel1.configureBlocking(false);
+                    assertFalse(channel1.isBlocking());
+                    datagramSocket1.close();
+                } catch (Exception e) {
+                    // do nothing
+                }
+            }
+        }.start();
+        SocketAddress addr = channel1.receive(buf);
+        assertNull(addr);
+    }
+
+    // -------------------------------------------------------------------
+    // Test for isConnected()
+    // -------------------------------------------------------------------
+
+    /**
+     * Test method for 'DatagramChannelImpl.isConnected()'
+     *
+     * @throws IOException
+     */
+    public void testIsConnected_WithServer() throws IOException {
+        connectLocalServer();
+        disconnectAfterConnected();
+        this.datagramSocket1.close();
+        this.channel1.close();
+        assertFalse(this.channel1.isConnected());
+    }
+
+    // -------------------------------------------------------------------
+    // Test for connect()
+    // -------------------------------------------------------------------
+
+    /**
+     * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+     */
+    public void testConnect_BlockWithServer() throws IOException {
+        // blocking mode
+        assertTrue(this.channel1.isBlocking());
+        connectLocalServer();
+        datagramSocket1.close();
+        disconnectAfterConnected();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+     */
+    public void testConnect_BlockNoServer() throws IOException {
+        connectWithoutServer();
+        disconnectAfterConnected();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+     *
+     * @throws IOException
+     */
+    public void testConnect_NonBlockWithServer() throws IOException {
+        // Non blocking mode
+        this.channel1.configureBlocking(false);
+        connectLocalServer();
+        datagramSocket1.close();
+        disconnectAfterConnected();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+     *
+     * @throws IOException
+     */
+    public void testConnect_Null() throws IOException {
+        assertFalse(this.channel1.isConnected());
+        try {
+            this.channel1.connect(null);
+            fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+     *
+     * @throws IOException
+     */
+    public void testConnect_UnsupportedType() throws IOException {
+        assertFalse(this.channel1.isConnected());
+        class SubSocketAddress extends SocketAddress {
+            private static final long serialVersionUID = 1L;
+
+            public SubSocketAddress() {
+                super();
+            }
+        }
+        SocketAddress newTypeAddress = new SubSocketAddress();
+        try {
+            this.channel1.connect(newTypeAddress);
+            fail("Should throw an UnsupportedAddressTypeException here.");
+        } catch (UnsupportedAddressTypeException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+     *
+     * @throws IOException
+     */
+    public void testConnect_Unresolved() throws IOException {
+        assertFalse(this.channel1.isConnected());
+        InetSocketAddress unresolved = new InetSocketAddress(
+                "unresolved address", 1080);
+        try {
+            this.channel1.connect(unresolved);
+            fail("Should throw an UnresolvedAddressException here."); //$NON-NLS-1$
+        } catch (UnresolvedAddressException e) {
+            // OK.
+        }
+    }
+
+    public void testConnect_EmptyHost() throws Exception {
+        assertFalse(this.channel1.isConnected());
+
+        assertEquals(this.channel1, this.channel1
+                .connect(new InetSocketAddress("", 1081))); //$NON-NLS-1$
+
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+     *
+     * @throws IOException
+     *
+     */
+    public void testConnect_ClosedChannelException() throws IOException {
+        assertFalse(this.channel1.isConnected());
+        this.channel1.close();
+        assertFalse(this.channel1.isOpen());
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw ClosedChannelException."); //$NON-NLS-1$
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+     *
+     * @throws IOException
+     *
+     */
+    public void testConnect_IllegalStateException() throws IOException {
+        assertFalse(this.channel1.isConnected());
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isConnected());
+        // connect after connected.
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw IllegalStateException."); //$NON-NLS-1$
+        } catch (IllegalStateException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+     *
+     * @throws IOException
+     *
+     */
+    public void testConnect_CheckOpenBeforeStatus() throws IOException {
+        assertFalse(this.channel1.isConnected());
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isConnected());
+        // connect after connected.
+        this.channel1.close();
+        assertFalse(this.channel1.isOpen());
+        // checking open is before checking status.
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw ClosedChannelException."); //$NON-NLS-1$
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+    }
+
+    private void disconnectAfterConnected() throws IOException {
+        assertTrue(this.channel1.isConnected());
+        this.channel1.disconnect();
+        assertFalse(this.channel1.isConnected());
+    }
+
+    private void disconnectAfterClosed() throws IOException {
+        assertFalse(this.channel1.isOpen());
+        assertFalse(this.channel1.isConnected());
+        this.channel1.disconnect();
+        assertFalse(this.channel1.isConnected());
+    }
+
+    private void connectLocalServer() throws IOException {
+        assertFalse(this.channel1.isConnected());
+        assertTrue(this.datagramSocket1.isBound());
+        assertSame(this.channel1, this.channel1.connect(localAddr1));
+        assertTrue(this.channel1.isConnected());
+    }
+
+    private void connectWithoutServer() throws IOException {
+        assertFalse(this.channel1.isConnected());
+        this.datagramSocket1.close();
+        assertTrue(this.datagramSocket1.isClosed());
+        assertSame(this.channel1, this.channel1.connect(localAddr1));
+        assertTrue(this.channel1.isConnected());
+    }
+
+    // -------------------------------------------------------------------
+    // Test for disconnect()
+    // -------------------------------------------------------------------
+
+    /**
+     * Test method for 'DatagramChannelImpl.disconnect()'
+     *
+     * @throws IOException
+     */
+    public void testDisconnect_BeforeConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());
+        assertEquals(this.channel1, this.channel1.disconnect());
+        assertFalse(this.channel1.isConnected());
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.disconnect()'
+     *
+     * @throws IOException
+     */
+    public void testDisconnect_UnconnectedClosed() throws IOException {
+        assertFalse(this.channel1.isConnected());
+        this.channel1.close();
+        assertFalse(this.channel1.isOpen());
+        assertEquals(this.channel1, this.channel1.disconnect());
+        assertFalse(this.channel1.isConnected());
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.disconnect()'
+     *
+     * @throws IOException
+     */
+    public void testDisconnect_BlockWithServerChannelClosed()
+            throws IOException {
+        assertTrue(this.channel1.isBlocking());
+        connectLocalServer();
+        // disconnect after channel close
+        this.channel1.close();
+        disconnectAfterClosed();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.disconnect()'
+     *
+     * @throws IOException
+     */
+    public void testDisconnect_NonBlockWithServerChannelClosed()
+            throws IOException {
+        this.channel1.configureBlocking(false);
+        connectLocalServer();
+        // disconnect after channel close
+        this.channel1.close();
+        disconnectAfterClosed();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.disconnect()'
+     *
+     * @throws IOException
+     */
+    public void testDisconnect_BlockWithServerServerClosed() throws IOException {
+        assertTrue(this.channel1.isBlocking());
+        connectLocalServer();
+        // disconnect after server close
+        this.datagramSocket1.close();
+        assertTrue(this.channel1.isOpen());
+        assertTrue(this.channel1.isConnected());
+        disconnectAfterConnected();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.disconnect()'
+     *
+     * @throws IOException
+     */
+    public void testDisconnect_NonBlockWithServerServerClosed()
+            throws IOException {
+        this.channel1.configureBlocking(false);
+        assertFalse(this.channel1.isBlocking());
+        connectLocalServer();
+        // disconnect after server close
+        this.datagramSocket1.close();
+        assertTrue(this.channel1.isOpen());
+        assertTrue(this.channel1.isConnected());
+        disconnectAfterConnected();
+    }
+
+    // -------------------------------------------------------------------
+    // Test for receive(): Behavior Without Server.
+    // -------------------------------------------------------------------
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_UnconnectedNull() throws Exception {
+        assertFalse(this.channel1.isConnected());
+        try {
+            this.channel1.receive(null);
+            fail("Should throw a NPE here."); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_UnconnectedReadonly() throws Exception {
+        assertFalse(this.channel1.isConnected());
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+                .asReadOnlyBuffer();
+        assertTrue(dst.isReadOnly());
+        try {
+            this.channel1.receive(dst);
+            fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_UnconnectedBufEmpty() throws Exception {
+        this.channel1.configureBlocking(false);
+        assertFalse(this.channel1.isConnected());
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        assertNull(this.channel1.receive(dst));
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_UnconnectedBufZero() throws Exception {
+        assertFalse(this.channel1.isConnected());
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_ZERO);
+        assertNull(this.channel1.receive(dst));
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_UnconnectedBufNotEmpty() throws Exception {
+        assertFalse(this.channel1.isConnected());
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        // buf is not empty
+        dst.put((byte) 88);
+        assertEquals(dst.position() + CAPACITY_NORMAL - 1, dst.limit());
+        assertNull(this.channel1.receive(dst));
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_UnconnectedBufFull() throws Exception {
+        assertFalse(this.channel1.isConnected());
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_ONE);
+        // buf is full
+        dst.put((byte) 88);
+        assertEquals(dst.position(), dst.limit());
+        assertNull(this.channel1.receive(dst));
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_UnconnectedClose() throws Exception {
+        assertFalse(this.channel1.isConnected());
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        this.channel1.close();
+        assertFalse(this.channel1.isOpen());
+        try {
+            assertNull(this.channel1.receive(dst));
+            fail("Should throw a ClosedChannelException here."); //$NON-NLS-1$
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_UnconnectedCloseNull() throws Exception {
+        assertFalse(this.channel1.isConnected());
+        this.channel1.close();
+        assertFalse(this.channel1.isOpen());
+        // checking buffer before checking open
+        try {
+            this.channel1.receive(null);
+            fail("Should throw a NPE here."); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_UnconnectedCloseReadonly() throws Exception {
+        assertFalse(this.channel1.isConnected());
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+                .asReadOnlyBuffer();
+        assertTrue(dst.isReadOnly());
+        this.channel1.close();
+        assertFalse(this.channel1.isOpen());
+        try {
+            this.channel1.receive(dst);
+            fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_NonBlockNoServerBufEmpty() throws Exception {
+        this.channel1.configureBlocking(false);
+        receiveNonBlockNoServer(CAPACITY_NORMAL);
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_BlockNoServerNull() throws Exception {
+        assertTrue(this.channel1.isBlocking());
+        receiveNoServerNull();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_NonBlockNoServerNull() throws Exception {
+        this.channel1.configureBlocking(false);
+        receiveNoServerNull();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_BlockNoServerReadonly() throws Exception {
+        assertTrue(this.channel1.isBlocking());
+        receiveNoServerReadonly();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_NonBlockNoServerReadonly() throws Exception {
+        this.channel1.configureBlocking(false);
+        receiveNoServerReadonly();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_NonBlockNoServerBufZero() throws Exception {
+        this.channel1.configureBlocking(false);
+        receiveNonBlockNoServer(CAPACITY_ZERO);
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_NonBlockNoServerBufNotEmpty() throws Exception {
+        this.channel1.configureBlocking(false);
+        connectWithoutServer();
+        ByteBuffer dst = allocateNonEmptyBuf();
+        assertNull(this.channel1.receive(dst));
+    }
+
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_NonBlockNoServerBufFull() throws Exception {
+        this.channel1.configureBlocking(false);
+        connectWithoutServer();
+        ByteBuffer dst = allocateFullBuf();
+        assertNull(this.channel1.receive(dst));
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_BlockNoServerChannelClose() throws Exception {
+        assertTrue(this.channel1.isBlocking());
+        receiveNoServerChannelClose();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_NonBlockNoServerChannelClose() throws Exception {
+        this.channel1.configureBlocking(false);
+        receiveNoServerChannelClose();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_BlockNoServerCloseNull() throws Exception {
+        assertTrue(this.channel1.isBlocking());
+        receiveNoServerChannelCloseNull();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_NonBlockNoServerCloseNull() throws Exception {
+        this.channel1.configureBlocking(false);
+        receiveNoServerChannelCloseNull();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_NonBlockNoServerCloseReadonly() throws Exception {
+        this.channel1.configureBlocking(false);
+        receiveNoServerChannelCloseReadonly();
+    }
+
+    /**
+     * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+     *
+     * @throws Exception
+     */
+    public void testReceive_BlockNoServerCloseReadonly() throws Exception {
+        assertTrue(this.channel1.isBlocking());
+        receiveNoServerChannelCloseReadonly();
+    }
+
+    private void receiveNoServerNull() throws IOException {
+        connectWithoutServer();
+        try {
+            this.channel1.receive(null);
+            fail("Should throw a NPE here."); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // OK.
+        }
+    }
+
+    private void receiveNoServerReadonly() throws IOException {
+        connectWithoutServer();
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+                .asReadOnlyBuffer();
+        assertTrue(dst.isReadOnly());
+        try {
+            this.channel1.receive(dst);
+            fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // OK.
+        }
+    }
+
+    private void receiveNonBlockNoServer(int size) throws IOException {
+        connectWithoutServer();
+        ByteBuffer dst = ByteBuffer.allocateDirect(size);
+        assertNull(this.channel1.receive(dst));
+    }
+
+    private void receiveNoServerChannelClose() throws IOException {
+        connectWithoutServer();
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        this.channel1.close();
+        assertFalse(this.channel1.isOpen());
+        try {
+            assertNull(this.channel1.receive(dst));
+            fail("Should throw a ClosedChannelException here."); //$NON-NLS-1$
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+    }
+
+    private void receiveNoServerChannelCloseNull() throws IOException {
+        connectWithoutServer();
+        this.channel1.close();
+        assertFalse(this.channel1.isOpen());
+        try {
+            this.channel1.receive(null);
+            fail("Should throw a NPE here."); //$NON-NLS-1$
+        } catch (NullPointerException e) {
+            // OK.
+        }
+    }
+
+    private void receiveNoServerChannelCloseReadonly() throws IOException {
+        connectWithoutServer();
+        this.channel1.close();
+        assertFalse(this.channel1.isOpen());
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+                .asReadOnlyBuffer();
+        assertTrue(dst.isReadOnly());
+        try {
+            this.channel1.receive(dst);
+            fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // OK.
+        }
+    }
+
+    private ByteBuffer allocateFullBuf() {
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_ONE);
+        // buf is full
+        dst.put((byte) 88);
+        assertEquals(dst.position(), dst.limit());
+        return dst;
+    }
+
+    private ByteBuffer allocateNonEmptyBuf() {
+        ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        // buf is not empty
+        dst.put((byte) 88);
+        dst.put((byte) 99);
+        assertEquals(dst.position() + CAPACITY_NORMAL - 2, dst.limit());
+        return dst;
+    }
+
+    // -------------------------------------------------------------------
+    // Test for send(): Behavior without server.
+    // -------------------------------------------------------------------
+
+    private void sendDataBlocking(InetSocketAddress addr, ByteBuffer writeBuf)
+            throws IOException {
+        InetSocketAddress ipAddr = addr;
+        assertEquals(CAPACITY_NORMAL, this.channel1.send(writeBuf, ipAddr));
+        assertTrue(this.channel1.isOpen());
+        assertTrue(this.channel1.isBlocking());
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+    }
+
+    private void sendDataNonBlocking(InetSocketAddress addr, ByteBuffer writeBuf)
+            throws IOException {
+        InetSocketAddress ipAddr = addr;
+        this.channel1.configureBlocking(false);
+        assertEquals(CAPACITY_NORMAL, this.channel1.send(writeBuf, ipAddr));
+        assertTrue(this.channel1.isOpen());
+        assertFalse(this.channel1.isBlocking());
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+    }
+
+    /*
+     * Test method for 'DatagramChannelImpl.send(ByteBuffer, SocketAddress)'
+     */
+    public void testSend_NoServerBlockingCommon() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        sendDataBlocking(localAddr1, writeBuf);
+    }
+
+    public void testSend_NoServerNonblockingCommon() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        sendDataNonBlocking(localAddr1, writeBuf);
+    }
+
+    public void testSend_NoServerTwice() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        sendDataBlocking(localAddr1, writeBuf);
+        // can not buffer twice!
+        assertEquals(0, this.channel1.send(writeBuf, localAddr1));
+        try {
+            channel1.send(writeBuf, localAddr2);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // correct
+        }
+    }
+
+    public void testSend_NoServerNonBlockingTwice() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        sendDataNonBlocking(localAddr1, writeBuf);
+        // can not buffer twice!
+        assertEquals(0, this.channel1.send(writeBuf, localAddr1));
+        try {
+            channel1.send(writeBuf, localAddr2);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // correct
+        }
+    }
+
+    public void testSend_NoServerBufNull() throws IOException {
+        try {
+            sendDataBlocking(localAddr1, null);
+            fail("Should throw a NPE here.");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    public void testSend_NoServerBufNullTwice() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        try {
+            sendDataBlocking(localAddr1, null);
+            fail("Should throw a NPE here.");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        sendDataBlocking(localAddr1, writeBuf);
+        try {
+            channel1.send(null, localAddr2);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    public void testSend_NoServerAddrNull() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        try {
+            sendDataBlocking(null, writeBuf);
+            fail("Should throw a NPE here.");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    public void testSend_NoServerAddrNullTwice() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        try {
+            sendDataBlocking(null, writeBuf);
+            fail("Should throw a NPE here.");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        sendDataBlocking(localAddr1, writeBuf);
+        try {
+            channel1.send(writeBuf, null);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Test for receive()and send(): Send and Receive with Real Data
+    // -------------------------------------------------------------------
+
+    public void testReceiveSend_Block_Normal() throws Exception {
+        this.channel1.socket().bind(localAddr2);
+        sendByChannel("some normal string in testReceiveSend_Normal",
+                localAddr2);
+        receiveByChannel(CAPACITY_NORMAL, localAddr2,
+                "some normal string in testReceiveSend_Normal");
+    }
+
+    public void testReceiveSend_Block_NotBound() throws Exception {
+        // not bound
+        sendByChannel("some normal string in testReceiveSend_Normal",
+                localAddr2);
+        ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+        assertNull(channel1.receive(buf));
+        assertFalse(channel1.socket().isBound());
+    }
+
+    public void testReceiveSend_NonBlock_NotBound() throws Exception {
+        // not bound
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+        sendByChannel("some normal string in testReceiveSend_Normal",
+                localAddr2);
+        ByteBuffer buf = ByteBuffer.wrap(new byte[CAPACITY_NORMAL]);
+        assertNull((InetSocketAddress) this.channel1.receive(buf));
+    }
+
+    public void testReceiveSend_Block_Normal_S2C() throws Exception {
+        this.channel1.socket().bind(localAddr2);
+        sendByDatagramSocket(
+                "some normal string in testReceiveSend_Normal_S2C", localAddr2);
+        receiveByChannel(CAPACITY_NORMAL, localAddr2,
+                "some normal string in testReceiveSend_Normal_S2C");
+    }
+
+    public void testReceiveSend_Block_Normal_C2S() throws Exception {
+        this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+        String str1 = "some normal string in testReceiveSend_Normal_C2S";
+        sendByChannel(str1, localAddr2);
+        receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, str1);
+    }
+
+    public void testReceiveSend_NonBlock_Normal_C2S() throws Exception {
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+        this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+        String str1 = "some normal string in testReceiveSend_Normal_C2S";
+        sendByChannel(str1, localAddr2);
+        receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, str1);
+    }
+
+    public void testReceiveSend_Normal_S2S() throws Exception {
+        String msg = "normal string in testReceiveSend_Normal_S2S";
+        this.datagramSocket1 = new DatagramSocket(testPort);
+        DatagramPacket rdp = new DatagramPacket(msg.getBytes(), msg.length(),
+                localAddr2);
+        datagramSocket2 = new DatagramSocket(localAddr2.getPort());
+        this.datagramSocket1.send(rdp);
+        byte[] buf = new byte[CAPACITY_NORMAL];
+        this.datagramSocket2.setSoTimeout(TIME_UNIT);
+        rdp = new DatagramPacket(buf, buf.length);
+        this.datagramSocket2.receive(rdp);
+        assertEquals(new String(buf, 0, CAPACITY_NORMAL).trim(), msg);
+    }
+
+    public void testReceiveSend_Block_Empty() throws Exception {
+        this.channel1.socket().bind(localAddr2);
+        sendByChannel("", localAddr2);
+        receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+    }
+
+    public void testReceiveSend_NonBlock_Empty() throws Exception {
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+        this.channel1.socket().bind(localAddr2);
+        sendByChannel("", localAddr2);
+        receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+    }
+
+    public void testReceiveSend_Block_Empty_S2C() throws Exception {
+        this.channel1.socket().bind(localAddr2);
+        sendByDatagramSocket("", localAddr2);
+        receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+    }
+
+    public void testReceiveSend_NonBlock_Empty_S2C() throws Exception {
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+        this.channel1.socket().bind(localAddr2);
+        sendByDatagramSocket("", localAddr2);
+        receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+    }
+
+    public void testReceiveSend_Block_Empty_C2S() throws Exception {
+        this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+        sendByChannel("", localAddr2);
+        receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, "");
+    }
+
+    public void testReceiveSend_NonBlock_Empty_C2S() throws Exception {
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+        this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+        sendByChannel("", localAddr2);
+        receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, "");
+    }
+
+    public void testReceiveSend_Empty_S2S() throws Exception {
+        String msg = "";
+        this.datagramSocket1 = new DatagramSocket(testPort);
+        DatagramPacket rdp = new DatagramPacket(msg.getBytes(), msg.length(),
+                localAddr2);
+        datagramSocket2 = new DatagramSocket(localAddr2.getPort());
+        this.datagramSocket1.send(rdp);
+        byte[] buf = new byte[CAPACITY_NORMAL];
+        this.datagramSocket2.setSoTimeout(TIME_UNIT);
+        rdp = new DatagramPacket(buf, buf.length);
+        this.datagramSocket2.receive(rdp);
+        assertEquals(new String(buf, 0, CAPACITY_NORMAL).trim(), msg);
+    }
+
+    public void testReceiveSend_Block_Oversize() throws Exception {
+        this.channel1.socket().bind(localAddr2);
+        sendByChannel("0123456789", localAddr2);
+        receiveByChannel(5, localAddr2, "01234");
+    }
+
+    public void testReceiveSend_Block_Oversize_C2S() throws Exception {
+        this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+        sendByChannel("0123456789", localAddr2);
+        receiveByDatagramSocket(5, localAddr2, "01234");
+    }
+
+    public void testReceiveSend_NonBlock_Oversize_C2S() throws Exception {
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+        this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+        sendByChannel("0123456789", localAddr2);
+        receiveByDatagramSocket(5, localAddr2, "01234");
+    }
+
+    public void testReceiveSend_Block_Oversize_S2C() throws Exception {
+        this.channel1.socket().bind(localAddr2);
+        sendByDatagramSocket("0123456789", localAddr2);
+        receiveByChannel(5, localAddr2, "01234");
+    }
+
+    public void testReceiveSend_8K() throws Exception {
+        StringBuffer str8k = new StringBuffer();
+        for (int i = 0; i < 8 * CAPACITY_1KB; i++) {
+            str8k.append('a');
+        }
+        String str = str8k.toString();
+        this.channel1.socket().bind(localAddr2);
+        sendByChannel(str, localAddr2);
+        receiveByChannel(8 * CAPACITY_1KB, localAddr2, str);
+    }
+
+    public void testReceiveSend_64K() throws Exception {
+        StringBuffer str64k = new StringBuffer();
+        for (int i = 0; i < CAPACITY_64KB; i++) {
+            str64k.append('a');
+        }
+        String str = str64k.toString();
+        try {
+            Thread.sleep(TIME_UNIT);
+            channel2.send(ByteBuffer.wrap(str.getBytes()), localAddr1);
+            fail("Should throw SocketException!");
+        } catch (SocketException e) {
+            //expected
+        }
+    }
+
+    private void sendByChannel(String data, InetSocketAddress address)
+            throws Exception {
+        try {
+            assertEquals(data.length(), this.channel2.send(ByteBuffer.wrap(data
+                    .getBytes()), address));
+        } finally {
+            this.channel2.close();
+        }
+    }
+
+    private void sendByDatagramSocket(String data, InetSocketAddress address)
+            throws Exception {
+        this.datagramSocket1 = new DatagramSocket(testPort);
+        DatagramPacket rdp = new DatagramPacket(data.getBytes(), data.length(),
+                address);
+        this.datagramSocket1.send(rdp);
+    }
+
+    private void receiveByChannel(int bufSize, InetSocketAddress address,
+            String expectedString) throws IOException {
+        try {
+            ByteBuffer buf = ByteBuffer.wrap(new byte[bufSize]);
+            InetSocketAddress returnAddr = null;
+            long startTime = System.currentTimeMillis();
+            do {
+                returnAddr = (InetSocketAddress) this.channel1.receive(buf);
+                // continue loop when channel1 is non-blocking and no data was
+                // received.
+                if (channel1.isBlocking() || null != returnAddr) {
+                    break;
+                }
+                // avoid dead loop
+                assertTimeout(startTime, 10000);
+            } while (true);
+            int length = returnAddr.getAddress().getAddress().length;
+            for (int i = 0; i < length; i++) {
+                assertEquals(returnAddr.getAddress().getAddress()[i],
+                        InetAddress.getByName("127.0.0.1").getAddress()[i]);
+            }
+            // port is NOT equal
+            assertFalse(returnAddr.getPort() == address.getPort());
+            assertEquals(new String(buf.array(), 0, bufSize).trim(),
+                    expectedString);
+        } finally {
+            this.channel1.close();
+        }
+    }
+
+    /*
+     * Fails if the difference between current time and start time is greater
+     * than timeout.
+     */
+    private void assertTimeout(long startTime, long timeout) {
+        long currentTime = System.currentTimeMillis();
+        if ((currentTime - startTime) > timeout) {
+            fail("Timeout");
+        }
+    }
+
+    private void receiveByDatagramSocket(int bufSize,
+            InetSocketAddress address, String expectedString)
+            throws IOException {
+        byte[] buf = new byte[bufSize];
+        this.datagramSocket1.setSoTimeout(6000);
+        DatagramPacket rdp = new DatagramPacket(buf, buf.length);
+        this.datagramSocket1.receive(rdp);
+        assertEquals(new String(buf, 0, bufSize).trim(), expectedString);
+    }
+
+    public void testRead_NoSecurity() throws Exception {
+        ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+        String strHello = "hello";
+        localAddr1 = new InetSocketAddress("127.0.0.1", testPort);
+        this.channel1.socket().bind(localAddr1);
+        this.channel2.socket().bind(localAddr2);
+        this.channel1.connect(localAddr2);
+        this.channel2.send(ByteBuffer.wrap(strHello.getBytes()), localAddr1);
+        assertEquals(strHello.length(), this.channel1.read(buf));
+        assertAscii(buf, strHello);
+    }
+
+    public void testReceive_Peek_NoSecurity_Nonblocking() throws Exception {
+        String strHello = "hello";
+        localAddr1 = new InetSocketAddress("127.0.0.1", testPort);
+        this.channel1.socket().bind(localAddr1);
+        sendByChannel(strHello, localAddr1);
+        this.channel1.configureBlocking(false);
+        // for accepted addr, no problem.
+        ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+        InetSocketAddress source = (InetSocketAddress) this.channel1.receive(buf);
+        assertEquals(localAddr1.getAddress(), source.getAddress());
+        assertAscii(buf, strHello);
+    }
+
+    private static void assertAscii(ByteBuffer b, String s) {
+        assertEquals(s.length(), b.position());
+        for (int i = 0; i < s.length(); ++i) {
+            assertEquals(s.charAt(i), b.get(i));
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Test for write()
+    // -------------------------------------------------------------------
+
+    private void connectWriteBuf(InetSocketAddress ipAddr, ByteBuffer buf)
+            throws IOException {
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(buf));
+        assertEquals(0, this.channel1.write(buf));
+    }
+
+    private void noconnectWrite(ByteBuffer buf) throws IOException {
+        try {
+            this.channel1.write(buf);
+            fail("should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+    }
+
+    /*
+     * Test method for 'DatagramChannelImpl.write(ByteBuffer)'
+     */
+    public void testWriteByteBuffer_Block() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        connectWriteBuf(localAddr1, writeBuf);
+    }
+
+    public void testWriteByteBuffer_NonBlock() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        this.channel1.configureBlocking(false);
+        connectWriteBuf(localAddr1, writeBuf);
+    }
+
+    public void testWriteByteBuffer_Block_closed() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        InetSocketAddress ipAddr = localAddr1;
+        noconnectWrite(writeBuf);
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        this.channel1.close();
+        try {
+            channel1.write(writeBuf);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBuffer_NonBlock_closed() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        InetSocketAddress ipAddr = localAddr1;
+        // non block mode
+        this.channel1.configureBlocking(false);
+        noconnectWrite(writeBuf);
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        this.channel1.close();
+        try {
+            channel1.write(writeBuf);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBuffer_Block_BufNull() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(0);
+        InetSocketAddress ipAddr = localAddr1;
+        try {
+            this.channel1.write((ByteBuffer) null);
+            fail("Should throw NPE.");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        try {
+            this.channel1.write((ByteBuffer) null);
+            fail("Should throw NPE.");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(0, this.channel1.write(writeBuf));
+        datagramSocket1.close();
+        try {
+            this.channel1.write((ByteBuffer) null);
+            fail("Should throw NPE.");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBuffer_NonBlock_BufNull() throws IOException {
+        ByteBuffer writeBuf = ByteBuffer.allocateDirect(0);
+        InetSocketAddress ipAddr = localAddr1;
+
+        // non block mode
+        this.channel1.configureBlocking(false);
+
+        try {
+            this.channel1.write((ByteBuffer) null);
+            fail("Should throw NPE.");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        try {
+            this.channel1.write((ByteBuffer) null);
+            fail("Should throw NPE.");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(0, this.channel1.write(writeBuf));
+        datagramSocket1.close();
+        try {
+            this.channel1.write((ByteBuffer) null);
+            fail("Should throw NPE.");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    /*
+     * Test method for 'DatagramChannelImpl.write(ByteBuffer[], int, int)'
+     */
+    public void testWriteByteBufferArrayIntInt_Block() throws IOException {
+        ByteBuffer[] writeBuf = new ByteBuffer[2];
+        writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        InetSocketAddress ipAddr = localAddr1;
+        try {
+            this.channel1.write(writeBuf, 0, 2);
+            fail("Should throw NotYetConnectedException.");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+        // cannot be buffered again!
+        assertEquals(0, this.channel1.write(writeBuf, 0, 1));
+
+    }
+
+    public void testWriteByteBufferArrayIntInt_NonBlock() throws IOException {
+        ByteBuffer[] writeBuf = new ByteBuffer[2];
+        writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        InetSocketAddress ipAddr = localAddr1;
+        // non-block mode
+        this.channel1.configureBlocking(false);
+        try {
+            this.channel1.write(writeBuf, 0, 2);
+            fail("Should throw NotYetConnectedException.");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+        // cannot be buffered again!
+        assertEquals(0, this.channel1.write(writeBuf, 0, 1));
+
+    }
+
+    public void testWriteByteBufferArrayIntInt_NoConnectIndexBad()
+            throws IOException {
+        ByteBuffer[] writeBuf = new ByteBuffer[2];
+        writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        InetSocketAddress ipAddr = localAddr1;
+        try {
+            this.channel1.write(writeBuf, -1, 2);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        try {
+            this.channel1.write(writeBuf, 0, -1);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+        // cannot be buffered again!
+        assertEquals(0, this.channel1.write(writeBuf, 0, 1));
+    }
+
+    public void testWriteByteBufferArrayIntInt_ConnectedIndexBad()
+            throws IOException {
+        ByteBuffer[] writeBuf = new ByteBuffer[2];
+        writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        InetSocketAddress ipAddr = localAddr1;
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        try {
+            this.channel1.write(writeBuf, -1, 2);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        try {
+            this.channel1.write(writeBuf, 0, -1);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBufferArrayIntInt_BufNullNoConnect()
+            throws IOException {
+        ByteBuffer[] writeBuf = new ByteBuffer[2];
+        writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        try {
+            this.channel1.write(null, 0, 2);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            this.channel1.write(writeBuf, -1, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            this.channel1.write(writeBuf, 0, 3);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+    }
+
+    public void testWriteByteBufferArrayIntInt_BufNullConnect()
+            throws IOException {
+        ByteBuffer[] writeBuf = new ByteBuffer[2];
+        writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        InetSocketAddress ipAddr = localAddr1;
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        try {
+            this.channel1.write(null, 0, 2);
+            fail("should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            this.channel1.write(writeBuf, 0, 3);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        datagramSocket1.close();
+        try {
+            this.channel1.write(null, 0, 2);
+            fail("should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Test for read()
+    // -------------------------------------------------------------------
+
+    /*
+     * Test method for 'DatagramChannelImpl.read(ByteBuffer)'
+     */
+    public void testReadByteBuffer() throws IOException {
+        ByteBuffer readBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        try {
+            this.channel1.read(readBuf);
+            fail("should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isConnected());
+        this.channel1.configureBlocking(false);
+        // note : blocking-mode will make the read process endless!
+        assertEquals(0, this.channel1.read(readBuf));
+        this.channel1.close();
+        try {
+            this.channel1.read(readBuf);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+    }
+
+    public void testReadByteBuffer_bufNull() throws IOException {
+        ByteBuffer readBuf = ByteBuffer.allocateDirect(0);
+        InetSocketAddress ipAddr = localAddr1;
+        try {
+            this.channel1.read(readBuf);
+            fail("should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        try {
+            channel1.read((ByteBuffer) null);
+            fail("should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        this.channel1.configureBlocking(false);
+        // note : blocking-mode will make the read process endless!
+        assertEquals(0, this.channel1.read(readBuf));
+        datagramSocket1.close();
+    }
+
+    /*
+     * Test method for 'DatagramChannelImpl.read(ByteBuffer[], int, int)'
+     */
+    public void testReadByteBufferArrayIntInt() throws IOException {
+        ByteBuffer[] readBuf = new ByteBuffer[2];
+        readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        readBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        InetSocketAddress ipAddr = localAddr1;
+        try {
+            this.channel1.read(readBuf, 0, 2);
+            fail("should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        this.channel1.configureBlocking(false);
+        // note : blocking-mode will make the read process endless!
+        assertEquals(0, this.channel1.read(readBuf, 0, 1));
+        assertEquals(0, this.channel1.read(readBuf, 0, 2));
+        datagramSocket1.close();
+    }
+
+    public void testReadByteBufferArrayIntInt_exceptions() throws IOException {
+        //regression test for HARMONY-932
+        try {
+            DatagramChannel.open().read(new ByteBuffer[] {}, 2, Integer.MAX_VALUE);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            DatagramChannel.open().read(new ByteBuffer[] {}, -1, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            DatagramChannel.open().read((ByteBuffer[]) null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void testReadByteBufferArrayIntInt_BufNull() throws IOException {
+        ByteBuffer[] readBuf = new ByteBuffer[2];
+        readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        InetSocketAddress ipAddr = localAddr1;
+        try {
+            this.channel1.read(null, 0, 0);
+            fail("should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        this.channel1.connect(ipAddr);
+        assertTrue(this.channel1.isConnected());
+        this.channel1.configureBlocking(false);
+        // note : blocking-mode will make the read process endless!
+        try {
+            this.channel1.read(null, 0, 0);
+            fail("should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(0, this.channel1.read(readBuf, 0, 1));
+        try {
+            this.channel1.read(readBuf, 0, 2);
+            fail("should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            this.channel1.read(readBuf, 0, 3);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        datagramSocket1.close();
+    }
+
+    // -------------------------------------------------------------------
+    // test read and write
+    // -------------------------------------------------------------------
+
+    public void testReadWrite_configureBlock() throws Exception {
+        byte[] targetArray = new byte[2];
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+
+        new Thread() {
+            public void run() {
+                try {
+                    Thread.sleep(TIME_UNIT);
+                    channel1.configureBlocking(false);
+                    channel1.close();
+                } catch (Exception e) {
+                    //ignore
+                }
+            }
+        }.start();
+        try {
+            this.channel1.read(targetBuf);
+            fail("should throw AsynchronousCloseException");
+        } catch (AsynchronousCloseException e) {
+            // ok
+        }
+    }
+
+    public void testReadWrite_Block_Zero() throws Exception {
+        byte[] sourceArray = new byte[0];
+        byte[] targetArray = new byte[0];
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        assertEquals(0, this.channel1.write(sourceBuf));
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+        int readCount = this.channel2.read(targetBuf);
+
+        assertEquals(0, readCount);
+    }
+
+    public void testReadWrite_Block_Normal() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_NORMAL];
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        readWriteReadData(this.channel1, sourceArray, this.channel2,
+                targetArray, CAPACITY_NORMAL, "testReadWrite_Block_Normal");
+    }
+
+    public void testReadWrite_Block_Empty() throws Exception {
+        // empty buf
+        byte[] sourceArray = "".getBytes();
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+
+        // bind and connect
+
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        assertEquals(0, this.channel1.write(sourceBuf));
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+        // empty message let the reader blocked
+        closeBlockedReaderChannel2(targetBuf);
+    }
+
+    public void testReadWrite_changeBlock_Empty() throws Exception {
+        // empty buf
+        byte[] sourceArray = "".getBytes();
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+
+        // bind and connect
+
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        assertEquals(0, this.channel1.write(sourceBuf));
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+        // empty message let the reader blocked
+        new Thread() {
+            public void run() {
+                try {
+                    Thread.sleep(TIME_UNIT);
+                    channel2.configureBlocking(false);
+                    Thread.sleep(TIME_UNIT * 5);
+                    channel2.close();
+                } catch (Exception e) {
+                    // do nothing
+                }
+            }
+        }.start();
+        try {
+            assertTrue(this.channel2.isBlocking());
+            this.channel2.read(targetBuf);
+            fail("Should throw AsynchronousCloseException");
+        } catch (AsynchronousCloseException e) {
+            assertFalse(this.channel2.isBlocking());
+            // OK.
+        }
+    }
+
+    public void testReadWrite_Block_8KB() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_1KB * 8];
+        byte[] targetArray = new byte[CAPACITY_1KB * 8];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        readWriteReadData(this.channel1, sourceArray, this.channel2,
+                targetArray, 8 * CAPACITY_1KB, "testReadWrite_Block_8KB");
+    }
+
+    /*
+     * sender write the sourceArray whose size is dataSize, and receiver read
+     * the data into targetArray
+     */
+    private void readWriteReadData(DatagramChannel sender, byte[] sourceArray,
+            DatagramChannel receiver, byte[] targetArray, int dataSize,
+            String methodName) throws IOException {
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        assertEquals(dataSize, sender.write(sourceBuf));
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+
+        int count = 0;
+        int total = 0;
+        long beginTime = System.currentTimeMillis();
+        while (total < dataSize && (count = receiver.read(targetBuf)) != -1) {
+            total = total + count;
+            // 3s timeout to avoid dead loop
+            if (System.currentTimeMillis() - beginTime > 3000){
+                break;
+            }
+        }
+
+        assertEquals(dataSize, total);
+        assertEquals(targetBuf.position(), total);
+        targetBuf.flip();
+        targetArray = targetBuf.array();
+        for (int i = 0; i < targetArray.length; i++) {
+            assertEquals(targetArray[i], (byte) i);
+        }
+    }
+
+    public void testReadWrite_Block_64K() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_64KB];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        try {
+            channel1.write(sourceBuf);
+            fail("Should throw IOException");
+        } catch (IOException e) {
+            // too big
+        }
+    }
+
+    public void testReadWrite_Block_DifferentAddr() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_NORMAL];
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr1);// the different addr
+
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+        // the wrong connected addr will make the read blocked.
+        // we close the blocked channel
+        closeBlockedReaderChannel2(targetBuf);
+    }
+
+    public void testReadWrite_Block_WriterNotBind() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_NORMAL];
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        // bind and connect
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+        closeBlockedReaderChannel2(targetBuf);
+    }
+
+    public void testReadWrite_Block_WriterBindLater() throws Exception {
+
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+
+        // bind and connect
+        // writer channel1 is bound later
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+        new Thread() {
+            public void run() {
+                try {
+                    Thread.sleep(TIME_UNIT);
+                    // bind later
+                    byte[] sourceArray = new byte[CAPACITY_NORMAL];
+                    for (int i = 0; i < sourceArray.length; i++) {
+                        sourceArray[i] = (byte) i;
+                    }
+                    channel1.socket().bind(localAddr2);
+                    channel1.connect(localAddr1);
+                    // write later
+                    ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+                    assertEquals(CAPACITY_NORMAL, channel1.write(sourceBuf));
+                } catch (Exception e) {
+                    // do nothing
+                }
+            }
+        }.start();
+
+        int count = 0;
+        int total = 0;
+        long beginTime = System.currentTimeMillis();
+        while (total < CAPACITY_NORMAL && (count = channel2.read(targetBuf)) != -1) {
+            total = total + count;
+            // 3s timeout to avoid dead loop
+            if (System.currentTimeMillis() - beginTime > 3000){
+                break;
+            }
+        }
+
+        assertEquals(CAPACITY_NORMAL, total);
+        assertEquals(targetBuf.position(), total);
+        targetBuf.flip();
+        targetArray = targetBuf.array();
+        for (int i = 0; i < targetArray.length; i++) {
+            assertEquals(targetArray[i], (byte) i);
+        }
+
+    }
+
+    public void testReadWrite_Block_ReaderNotBind() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_NORMAL];
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        // reader channel2 is not bound
+        this.channel2.connect(localAddr2);
+
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+        closeBlockedReaderChannel2(targetBuf);
+
+    }
+
+    private void closeBlockedReaderChannel2(ByteBuffer targetBuf)
+            throws IOException {
+        new Thread() {
+            public void run() {
+                try {
+                    Thread.sleep(TIME_UNIT);
+                    channel2.close();
+                } catch (Exception e) {
+                    // do nothing
+                }
+            }
+        }.start();
+        try {
+            assertTrue(this.channel2.isBlocking());
+            this.channel2.read(targetBuf);
+            fail("Should throw AsynchronousCloseException");
+        } catch (AsynchronousCloseException e) {
+            // OK.
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Test read and write in non-block mode.
+    // -------------------------------------------------------------------
+    public void testReadWrite_NonBlock_Normal() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_NORMAL];
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        readWriteReadData(this.channel1, sourceArray, this.channel2,
+                targetArray, CAPACITY_NORMAL, "testReadWrite_NonBlock_Normal");
+    }
+
+    public void testReadWrite_NonBlock_8KB() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_1KB * 8];
+        byte[] targetArray = new byte[CAPACITY_1KB * 8];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        readWriteReadData(this.channel1, sourceArray, this.channel2,
+                targetArray, 8 * CAPACITY_1KB, "testReadWrite_NonBlock_8KB");
+    }
+
+    public void testReadWrite_NonBlock_DifferentAddr() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_NORMAL];
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr1);// the different addr
+
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+        assertEquals(0, this.channel2.read(targetBuf));
+    }
+
+    public void testReadWrite_NonBlock_WriterNotBind() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_NORMAL];
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+
+        // bind and connect
+        this.channel1.connect(localAddr1);
+        this.channel2.socket().bind(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+        assertEquals(0, this.channel2.read(targetBuf));
+    }
+
+    public void testReadWrite_NonBlock_ReaderNotBind() throws Exception {
+        byte[] sourceArray = new byte[CAPACITY_NORMAL];
+        byte[] targetArray = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < sourceArray.length; i++) {
+            sourceArray[i] = (byte) i;
+        }
+
+        this.channel1.configureBlocking(false);
+        this.channel2.configureBlocking(false);
+
+        // bind and connect
+        this.channel1.socket().bind(localAddr2);
+        this.channel1.connect(localAddr1);
+        this.channel2.connect(localAddr2);
+
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+        // read
+        ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+        assertEquals(0, this.channel2.read(targetBuf));
+    }
+
+    public void test_write_LBuffer_positioned() throws Exception {
+        // Regression test for Harmony-683
+        int position = 16;
+        DatagramChannel dc = DatagramChannel.open();
+        byte[] sourceArray = new byte[CAPACITY_NORMAL];
+        dc.connect(localAddr1);
+        // write
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        sourceBuf.position(position);
+        assertEquals(CAPACITY_NORMAL - position, dc.write(sourceBuf));
+    }
+
+    public void test_send_LBuffer_LSocketAddress_PositionNotZero()
+            throws Exception {
+        // regression test for Harmony-701
+        int CAPACITY_NORMAL = 256;
+        int position = 16;
+        DatagramChannel dc = DatagramChannel.open();
+        byte[] sourceArray = new byte[CAPACITY_NORMAL];
+        // send ByteBuffer whose position is not zero
+        ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+        sourceBuf.position(position);
+        int ret = dc.send(sourceBuf, localAddr1);
+        // assert send (256 - 16) bytes
+        assertEquals(CAPACITY_NORMAL - position, ret);
+        // assert the position of ByteBuffer has been set
+        assertEquals(CAPACITY_NORMAL, sourceBuf.position());
+    }
+
+    /**
+     * @tests DatagramChannel#read(ByteBuffer[])
+     */
+    public void test_read_$LByteBuffer() throws Exception {
+        // regression test for Harmony-754
+        channel2.socket().bind(localAddr1);
+        channel1.socket().bind(localAddr2);
+        channel1.connect(localAddr1);
+        channel2.connect(localAddr2);
+        channel2.write(ByteBuffer.allocate(CAPACITY_NORMAL));
+
+        ByteBuffer[] readBuf = new ByteBuffer[2];
+        readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        readBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+
+        channel1.configureBlocking(true);
+        assertEquals(CAPACITY_NORMAL, channel1.read(readBuf));
+    }
+
+    /**
+     * @tests DatagramChannel#read(ByteBuffer[],int,int)
+     */
+    public void test_read_$LByteBufferII() throws Exception {
+        // regression test for Harmony-754
+        channel2.socket().bind(localAddr1);
+        channel1.socket().bind(localAddr2);
+        channel1.connect(localAddr1);
+        channel2.connect(localAddr2);
+        channel2.write(ByteBuffer.allocate(CAPACITY_NORMAL));
+
+        ByteBuffer[] readBuf = new ByteBuffer[2];
+        readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        readBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+
+        channel1.configureBlocking(true);
+        assertEquals(CAPACITY_NORMAL, channel1.read(readBuf,0,2));
+    }
+
+    /**
+     * @tests DatagramChannel#read(ByteBuffer)
+     */
+    public void test_read_LByteBuffer_closed_nullBuf() throws Exception {
+        // regression test for Harmony-754
+        ByteBuffer c = null;
+        DatagramChannel channel = DatagramChannel.open();
+        channel.close();
+        try{
+            channel.read(c);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e){
+            // expected
+        }
+    }
+
+    /**
+     * @tests DatagramChannel#read(ByteBuffer)
+     */
+    public void test_read_LByteBuffer_NotConnected_nullBuf() throws Exception {
+        // regression test for Harmony-754
+        ByteBuffer c = null;
+        DatagramChannel channel = DatagramChannel.open();
+        try{
+            channel.read(c);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e){
+            // expected
+        }
+    }
+
+    /**
+     * @tests DatagramChannel#read(ByteBuffer)
+     */
+    public void test_read_LByteBuffer_readOnlyBuf() throws Exception {
+        // regression test for Harmony-754
+        ByteBuffer c = ByteBuffer.allocate(1);
+        DatagramChannel channel = DatagramChannel.open();
+        try{
+            channel.read(c.asReadOnlyBuffer());
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e){
+        } catch (IllegalArgumentException e){
+            // expected
+        }
+        channel.connect(localAddr1);
+        try{
+            channel.read(c.asReadOnlyBuffer());
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e){
+            // expected
+        }
+    }
+
+    /**
+     * @tests DatagramChannel#send(ByteBuffer, SocketAddress)
+     */
+    public void test_send_LByteBuffer_LSocketAddress_closed() throws IOException{
+        // regression test for Harmony-913
+        channel1.close();
+        ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+        try {
+            channel1.send(buf, localAddr1);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            //pass
+        }
+        try {
+            channel1.send(null,localAddr1);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            //pass
+        }
+        try {
+            channel1.send(buf, null);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            //pass
+        }
+        try {
+            channel1.send(null, null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            //pass
+        }
+    }
+
+    /**
+     * @tests DatagramChannel#socket()
+     */
+    public void test_socket_IllegalBlockingModeException() throws Exception {
+        // regression test for Harmony-1036
+        DatagramChannel channel = DatagramChannel.open();
+        channel.configureBlocking(false);
+        DatagramSocket socket = channel.socket();
+        try {
+            socket.send(null);
+            fail("should throw IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+        try {
+            socket.receive(null);
+            fail("should throw IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+    }
+
+    public void test_bounded_harmony6493() throws IOException {
+        DatagramChannel server = DatagramChannel.open();
+        InetSocketAddress addr = new InetSocketAddress("localhost", 0);
+        server.socket().bind(addr);
+        SocketAddress boundedAddress = server.socket().getLocalSocketAddress();
+
+        DatagramChannel client = DatagramChannel.open();
+        ByteBuffer sent = ByteBuffer.allocate(1024);
+        sent.put("test".getBytes());
+        sent.flip();
+        client.send(sent, boundedAddress);
+        assertTrue(client.socket().isBound());
+
+        server.close();
+        client.close();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelLockingTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelLockingTest.java
new file mode 100644
index 0000000..cb34343
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelLockingTest.java
@@ -0,0 +1,208 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.NonReadableChannelException;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.OverlappingFileLockException;
+
+import junit.framework.TestCase;
+
+/**
+ * API tests for the NIO FileChannel locking APIs
+ */
+public class FileChannelLockingTest extends TestCase {
+
+    private FileChannel readOnlyChannel;
+
+    private FileChannel writeOnlyChannel;
+
+    private FileChannel readWriteChannel;
+
+    private final String CONTENT = "The best things in life are nearest: Breath in your nostrils, light in your eyes, "
+            + "flowers at your feet, duties at your hand, the path of right just before you. Then do not grasp at the stars, "
+            + "but do life's plain, common work as it comes, certain that daily duties and daily bread are the sweetest "
+            + " things in life.--Robert Louis Stevenson";
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Create a three temporary files with content.
+        File[] tempFiles = new File[3];
+        for (int i = 0; i < tempFiles.length; i++) {
+            tempFiles[i] = File.createTempFile("testing", "tmp");
+            tempFiles[i].deleteOnExit();
+            FileWriter writer = new FileWriter(tempFiles[i]);
+            writer.write(CONTENT);
+            writer.close();
+        }
+
+        // Open read, write, and read/write channels on the temp files.
+        FileInputStream fileInputStream = new FileInputStream(tempFiles[0]);
+        readOnlyChannel = fileInputStream.getChannel();
+
+        FileOutputStream fileOutputStream = new FileOutputStream(tempFiles[1]);
+        writeOnlyChannel = fileOutputStream.getChannel();
+
+        RandomAccessFile randomAccessFile = new RandomAccessFile(tempFiles[2],
+                "rw");
+        readWriteChannel = randomAccessFile.getChannel();
+    }
+
+    protected void tearDown() throws IOException {
+        if (readOnlyChannel != null) {
+            readOnlyChannel.close();
+        }
+        if (writeOnlyChannel != null) {
+            writeOnlyChannel.close();
+        }
+        if (readWriteChannel != null) {
+            readWriteChannel.close();
+        }
+    }
+
+    public void test_illegalLocks() throws IOException {
+        // Cannot acquire an exclusive lock on a read-only file channel
+        try {
+            readOnlyChannel.lock();
+            fail("Acquiring a full exclusive lock on a read only channel should fail.");
+        } catch (NonWritableChannelException ex) {
+            // Expected.
+        }
+
+        // Cannot get a shared lock on a write-only file channel.
+        try {
+            writeOnlyChannel.lock(1, 10, true);
+            fail("Acquiring a shared lock on a write-only channel should fail.");
+        } catch (NonReadableChannelException ex) {
+            // expected
+        }
+    }
+
+    public void test_lockReadWrite() throws IOException {
+        // Acquire an exclusive lock across the entire file.
+        FileLock flock = readWriteChannel.lock();
+        if (flock != null) {
+            flock.release();
+        }
+    }
+
+    public void test_illegalLockParameters() throws IOException {
+        // Cannot lock negative positions
+        try {
+            readOnlyChannel.lock(-1, 10, true);
+            fail("Passing illegal args to lock should fail.");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+        try {
+            writeOnlyChannel.lock(-1, 10, false);
+            fail("Passing illegal args to lock should fail.");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+        try {
+            readWriteChannel.lock(-1, 10, false);
+            fail("Passing illegal args to lock should fail.");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+
+        // Lock a range at the front, shared.
+        FileLock flock1 = readWriteChannel.lock(22, 110, true);
+
+        // Try to acquire an overlapping lock.
+        try {
+            readWriteChannel.lock(75, 210, true);
+        } catch (OverlappingFileLockException exception) {
+            // expected
+            flock1.release();
+        }
+    }
+
+    public void test_lockLLZ() throws IOException {
+        // Lock a range at the front, non-shared.
+        FileLock flock1 = readWriteChannel.lock(0, 10, false);
+
+        // Lock a shared range further in the same file.
+        FileLock flock2 = readWriteChannel.lock(22, 100, true);
+
+        // The spec allows the impl to refuse shared locks
+        flock1.release();
+        flock2.release();
+    }
+
+    public void test_tryLock() throws IOException {
+        try {
+            readOnlyChannel.tryLock();
+            fail("Acquiring a full exclusive lock on a read channel should have thrown an exception.");
+        } catch (NonWritableChannelException ex) {
+            // Expected.
+        }
+    }
+
+    public void test_tryLockLLZ() throws IOException {
+        // It is illegal to request an exclusive lock on a read-only channel
+        try {
+            readOnlyChannel.tryLock(0, 99, false);
+            fail("Acquiring exclusive lock on read-only channel should fail");
+        } catch (NonWritableChannelException ex) {
+            // Expected
+        }
+
+        // It is invalid to request a lock starting before the file start
+        try {
+            readOnlyChannel.tryLock(-99, 0, true);
+            fail("Acquiring an illegal lock value should fail.");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+
+        // Acquire a valid lock
+        FileLock tmpLock = readOnlyChannel.tryLock(0, 10, true);
+        assertTrue(tmpLock.isValid());
+        tmpLock.release();
+
+        // Acquire another valid lock -- and don't release it yet
+        FileLock lock = readOnlyChannel.tryLock(10, 788, true);
+        assertTrue(lock.isValid());
+
+        // Overlapping locks are illegal
+        try {
+            readOnlyChannel.tryLock(1, 23, true);
+            fail("Acquiring an overlapping lock should fail.");
+        } catch (OverlappingFileLockException ex) {
+            // Expected
+        }
+
+        // Adjacent locks are legal
+        FileLock adjacentLock = readOnlyChannel.tryLock(1, 3, true);
+        assertTrue(adjacentLock.isValid());
+        adjacentLock.release();
+
+        // Release longer lived lock
+        lock.release();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
new file mode 100644
index 0000000..9a89f7e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
@@ -0,0 +1,3121 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.NonReadableChannelException;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.channels.Pipe;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.channels.FileChannel.MapMode;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+public class FileChannelTest extends TestCase {
+
+    private static final int CAPACITY = 100;
+
+    private static final int LIMITED_CAPACITY = 2;
+
+    private static final int TIME_OUT = 10000;
+
+    private static final String CONTENT = "MYTESTSTRING needs to be a little long";
+
+    private static final byte[] TEST_BYTES;
+
+    private static final byte[] CONTENT_AS_BYTES;
+
+    private static final int CONTENT_AS_BYTES_LENGTH;
+
+    static {
+        try {
+            TEST_BYTES = "test".getBytes("iso8859-1");
+            CONTENT_AS_BYTES = CONTENT.getBytes("iso8859-1");
+            CONTENT_AS_BYTES_LENGTH = CONTENT_AS_BYTES.length;
+        } catch (UnsupportedEncodingException e) {
+            throw new Error(e);
+        }
+    }
+
+    private static final int CONTENT_LENGTH = CONTENT.length();
+
+    private FileChannel readOnlyFileChannel;
+
+    private FileChannel writeOnlyFileChannel;
+
+    private FileChannel readWriteFileChannel;
+
+    private File fileOfReadOnlyFileChannel;
+
+    private File fileOfWriteOnlyFileChannel;
+
+    private File fileOfReadWriteFileChannel;
+
+    private ReadableByteChannel readByteChannel;
+
+    private WritableByteChannel writableByteChannel;
+
+    private DatagramChannel datagramChannelSender;
+
+    private DatagramChannel datagramChannelReceiver;
+
+    private ServerSocketChannel serverSocketChannel;
+
+    private SocketChannel socketChannelSender;
+
+    private SocketChannel socketChannelReceiver;
+
+    private Pipe pipe;
+
+    // to read content from FileChannel
+    private FileInputStream fis;
+
+    private FileLock fileLock;
+
+    protected void setUp() throws Exception {
+        fileOfReadOnlyFileChannel = File.createTempFile(
+                "File_of_readOnlyFileChannel", "tmp");
+        fileOfReadOnlyFileChannel.deleteOnExit();
+        fileOfWriteOnlyFileChannel = File.createTempFile(
+                "File_of_writeOnlyFileChannel", "tmp");
+        fileOfWriteOnlyFileChannel.deleteOnExit();
+        fileOfReadWriteFileChannel = File.createTempFile(
+                "File_of_readWriteFileChannel", "tmp");
+        fileOfReadWriteFileChannel.deleteOnExit();
+        fis = null;
+        fileLock = null;
+        readOnlyFileChannel = new FileInputStream(fileOfReadOnlyFileChannel)
+                .getChannel();
+        writeOnlyFileChannel = new FileOutputStream(fileOfWriteOnlyFileChannel)
+                .getChannel();
+        readWriteFileChannel = new RandomAccessFile(fileOfReadWriteFileChannel,
+                "rw").getChannel();
+    }
+
+    protected void tearDown() {
+        if (null != readOnlyFileChannel) {
+            try {
+                readOnlyFileChannel.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+        if (null != writeOnlyFileChannel) {
+            try {
+                writeOnlyFileChannel.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+        if (null != readWriteFileChannel) {
+            try {
+                readWriteFileChannel.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+        if (null != fis) {
+            try {
+                fis.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+
+        if (null != fileLock) {
+            try {
+                fileLock.release();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+
+        if (null != fileOfReadOnlyFileChannel) {
+            fileOfReadOnlyFileChannel.delete();
+        }
+        if (null != fileOfWriteOnlyFileChannel) {
+            fileOfWriteOnlyFileChannel.delete();
+        }
+        if (null != fileOfReadWriteFileChannel) {
+            fileOfReadWriteFileChannel.delete();
+        }
+        if (null != datagramChannelSender) {
+            try {
+                datagramChannelSender.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+        if (null != datagramChannelReceiver) {
+            try {
+                datagramChannelReceiver.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+        if (null != serverSocketChannel) {
+            try {
+                serverSocketChannel.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+        if (null != socketChannelSender) {
+            try {
+                socketChannelSender.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+        if (null != socketChannelReceiver) {
+            try {
+                socketChannelReceiver.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+        if (null != pipe) {
+            if (null != pipe.source()) {
+                try {
+                    pipe.source().close();
+                } catch (IOException e) {
+                    // do nothing
+                }
+            }
+            if (null != pipe.sink()) {
+                try {
+                    pipe.sink().close();
+                } catch (IOException e) {
+                    // do nothing
+                }
+            }
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#force(boolean)
+     */
+    public void test_forceJ() throws Exception {
+        ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+        writeOnlyFileChannel.write(writeBuffer);
+        writeOnlyFileChannel.force(true);
+
+        byte[] readBuffer = new byte[CONTENT_AS_BYTES_LENGTH];
+        fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+        fis.read(readBuffer);
+        assertTrue(Arrays.equals(CONTENT_AS_BYTES, readBuffer));
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#force(boolean)
+     */
+    public void test_forceJ_closed() throws Exception {
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.force(true);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+
+        try {
+            writeOnlyFileChannel.force(false);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#force(boolean)
+     */
+    public void test_forceJ_ReadOnlyChannel() throws Exception {
+        // force on a read only file channel has no effect.
+        readOnlyFileChannel.force(true);
+        readOnlyFileChannel.force(false);
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#position()
+     */
+    public void test_position_Init() throws Exception {
+        assertEquals(0, readOnlyFileChannel.position());
+        assertEquals(0, writeOnlyFileChannel.position());
+        assertEquals(0, readWriteFileChannel.position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#position()
+     */
+    public void test_position_ReadOnly() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+
+        assertEquals(0, readOnlyFileChannel.position());
+        ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+        readOnlyFileChannel.read(readBuffer);
+        assertEquals(CONTENT_LENGTH, readOnlyFileChannel.position());
+    }
+
+    /**
+     * Initializes test file.
+     *
+     * @param file
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    private void writeDataToFile(File file) throws FileNotFoundException,
+            IOException {
+        FileOutputStream fos = new FileOutputStream(file);
+        try {
+            fos.write(CONTENT_AS_BYTES);
+        } finally {
+            fos.close();
+        }
+    }
+
+    /**
+     * Initializes large test file.
+     *
+     * @param file the file to be written
+     * @param size the content size to be written
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    private void writeLargeDataToFile(File file, int size) throws FileNotFoundException,
+            IOException {
+        FileOutputStream fos = new FileOutputStream(file);
+        byte[] buf = new byte[size];
+
+        try {
+            // we don't care about content - just need a particular file size
+            fos.write(buf);
+        } finally {
+            fos.close();
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#position()
+     */
+    public void test_position_WriteOnly() throws Exception {
+        ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+        writeOnlyFileChannel.write(writeBuffer);
+        assertEquals(CONTENT_LENGTH, writeOnlyFileChannel.position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#position()
+     */
+    public void test_position_ReadWrite() throws Exception {
+        writeDataToFile(fileOfReadWriteFileChannel);
+
+        assertEquals(0, readWriteFileChannel.position());
+        ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+        readWriteFileChannel.read(readBuffer);
+        assertEquals(CONTENT_LENGTH, readWriteFileChannel.position());
+
+        ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+        readWriteFileChannel.write(writeBuffer);
+        assertEquals(CONTENT_LENGTH * 2, readWriteFileChannel.position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#position()
+     */
+    public void test_position_Closed() throws Exception {
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.position();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.position();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.position();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#position(long)
+     */
+    public void test_positionJ_Closed() throws Exception {
+        final long POSITION = 100;
+
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.position(POSITION);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.position(POSITION);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.position(POSITION);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#position(long)
+     */
+    public void test_positionJ_Negative() throws Exception {
+        final long NEGATIVE_POSITION = -1;
+        try {
+            readOnlyFileChannel.position(NEGATIVE_POSITION);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            writeOnlyFileChannel.position(NEGATIVE_POSITION);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.position(NEGATIVE_POSITION);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#position(long)
+     */
+    public void test_positionJ_ReadOnly() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+
+        // set the position of the read only file channel to POSITION
+        final int POSITION = 4;
+        readOnlyFileChannel.position(POSITION);
+
+        // reads the content left to readBuffer through read only file channel
+        ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+        int count = readOnlyFileChannel.read(readBuffer);
+        assertEquals(CONTENT_LENGTH - POSITION, count);
+
+        // asserts the content read is the part which stays beyond the POSITION
+        readBuffer.flip();
+        int i = POSITION;
+        while (readBuffer.hasRemaining()) {
+            assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+            i++;
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#position(long)
+     */
+    public void test_positionJ_WriteOnly() throws Exception {
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        // init data to write
+        ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+
+        // set the position of the write only file channel to POSITION
+        final int POSITION = 4;
+        writeOnlyFileChannel.position(POSITION);
+
+        // writes to the write only file channel
+        writeOnlyFileChannel.write(writeBuffer);
+        // force to write out.
+        writeOnlyFileChannel.close();
+
+        // gets the result of the write only file channel
+        byte[] result = new byte[POSITION + CONTENT_LENGTH];
+        fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+        fis.read(result);
+
+        // constructs the expected result which has content[0... POSITION] plus
+        // content[0...length()]
+        byte[] expectedResult = new byte[POSITION + CONTENT_LENGTH];
+        System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, 0, POSITION);
+        System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, POSITION,
+                CONTENT_LENGTH);
+
+        // asserts result of the write only file channel same as expected
+        assertTrue(Arrays.equals(expectedResult, result));
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#size()
+     */
+    public void test_size_Init() throws Exception {
+        assertEquals(0, readOnlyFileChannel.size());
+        assertEquals(0, writeOnlyFileChannel.size());
+        assertEquals(0, readWriteFileChannel.size());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#size()
+     */
+    public void test_size() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        assertEquals(fileOfReadOnlyFileChannel.length(), readOnlyFileChannel
+                .size());
+
+
+        // REGRESSION test for read(ByteBuffer[], int, int) on special files
+        try {
+            FileChannel specialFile =
+                new FileInputStream("/dev/zero").getChannel();
+            assertEquals(0, specialFile.size());
+            ByteBuffer buf = ByteBuffer.allocate(8);
+            assertEquals(8, specialFile.read(buf));
+            ByteBuffer[] bufs = { ByteBuffer.allocate(8) };
+            assertEquals(8, specialFile.read(bufs, 0, 1));
+            specialFile.close();
+        } catch (FileNotFoundException e) {
+            // skip test if special file doesn't exist
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#size()
+     */
+    public void test_size_Closed() throws Exception {
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.size();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.size();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.size();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#truncate(long)
+     */
+    public void test_truncateJ_Closed() throws Exception {
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.truncate(0);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.truncate(0);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.truncate(-1);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#truncate(long)
+     */
+    public void test_truncateJ_IllegalArgument() throws Exception {
+        // regression test for Harmony-941
+        try {
+            readOnlyFileChannel.truncate(-1);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            writeOnlyFileChannel.truncate(-1);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.truncate(-1);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#truncate(long)
+     */
+    public void test_truncateJ_ReadOnly() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        try {
+            readOnlyFileChannel.truncate(readOnlyFileChannel.size());
+            fail("should throw NonWritableChannelException.");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+
+        try {
+            readOnlyFileChannel.truncate(0);
+            fail("should throw NonWritableChannelException.");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#truncate(long)
+     */
+    public void test_truncateJ() throws Exception {
+        writeDataToFile(fileOfReadWriteFileChannel);
+
+        int truncateLength = CONTENT_LENGTH + 2;
+        assertEquals(readWriteFileChannel, readWriteFileChannel
+                .truncate(truncateLength));
+        assertEquals(CONTENT_LENGTH, fileOfReadWriteFileChannel.length());
+
+        truncateLength = CONTENT_LENGTH;
+        assertEquals(readWriteFileChannel, readWriteFileChannel
+                .truncate(truncateLength));
+        assertEquals(CONTENT_LENGTH, fileOfReadWriteFileChannel.length());
+
+        truncateLength = CONTENT_LENGTH / 2;
+        assertEquals(readWriteFileChannel, readWriteFileChannel
+                .truncate(truncateLength));
+        assertEquals(truncateLength, fileOfReadWriteFileChannel.length());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock()
+     */
+    public void test_lock() throws Exception {
+        MockFileChannel mockFileChannel = new MockFileChannel();
+        // Verify that calling lock() leads to the method
+        // lock(long, long, boolean) being called with a 0 for the
+        // first parameter, Long.MAX_VALUE as the second parameter and false
+        // as the third parameter.
+        mockFileChannel.lock();
+        assertTrue(mockFileChannel.isLockCalled);
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+     */
+    public void test_lockJJZ_Closed() throws Exception {
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.lock(0, 10, false);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.lock(0, 10, false);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.lock(0, 10, false);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        // throws ClosedChannelException before IllegalArgumentException
+        try {
+            readWriteFileChannel.lock(-1, 0, false);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+     */
+    public void test_lockJJZ_IllegalArgument() throws Exception {
+        try {
+            writeOnlyFileChannel.lock(0, -1, false);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            writeOnlyFileChannel.lock(-1, 0, false);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.lock(-1, -1, false);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.lock(Long.MAX_VALUE, 1, false);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+     */
+    public void test_lockJJZ_NonWritable() throws Exception {
+        try {
+            readOnlyFileChannel.lock(0, 10, false);
+            fail("should throw NonWritableChannelException");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+
+        // throws NonWritableChannelException before IllegalArgumentException
+        try {
+            readOnlyFileChannel.lock(-1, 0, false);
+            fail("should throw NonWritableChannelException");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+     */
+    public void test_lockJJZ_NonReadable() throws Exception {
+        try {
+            writeOnlyFileChannel.lock(0, 10, true);
+            fail("should throw NonReadableChannelException");
+        } catch (NonReadableChannelException e) {
+            // expected
+        }
+
+        // throws NonReadableChannelException before IllegalArgumentException
+        try {
+            writeOnlyFileChannel.lock(-1, 0, true);
+            fail("should throw NonReadableChannelException");
+        } catch (NonReadableChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+     */
+    public void test_lockJJZ_Shared() throws Exception {
+        final long POSITION = 100;
+        final long SIZE = 200;
+        fileLock = readOnlyFileChannel.lock(POSITION, SIZE, true);
+        assertTrue(fileLock.isValid());
+        // fileLock.isShared depends on whether the underlying platform support
+        // shared lock, but it works on Windows & Linux.
+        assertTrue(fileLock.isShared());
+        assertSame(readOnlyFileChannel, fileLock.channel());
+        assertEquals(POSITION, fileLock.position());
+        assertEquals(SIZE, fileLock.size());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+     */
+    public void test_lockJJZ_NotShared() throws Exception {
+        final long POSITION = 100;
+        final long SIZE = 200;
+        fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+        assertTrue(fileLock.isValid());
+        assertFalse(fileLock.isShared());
+        assertSame(writeOnlyFileChannel, fileLock.channel());
+        assertEquals(POSITION, fileLock.position());
+        assertEquals(SIZE, fileLock.size());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+     */
+    public void test_lockJJZ_Long_MAX_VALUE() throws Exception {
+        final long POSITION = 0;
+        final long SIZE = Long.MAX_VALUE;
+        fileLock = readOnlyFileChannel.lock(POSITION, SIZE, true);
+        assertTrue(fileLock.isValid());
+        assertTrue(fileLock.isShared());
+        assertEquals(POSITION, fileLock.position());
+        assertEquals(SIZE, fileLock.size());
+        assertSame(readOnlyFileChannel, fileLock.channel());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+     */
+    public void test_lockJJZ_Overlapping() throws Exception {
+        final long POSITION = 100;
+        final long SIZE = 200;
+        fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+        assertTrue(fileLock.isValid());
+
+        try {
+            writeOnlyFileChannel.lock(POSITION + 1, SIZE, false);
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+     */
+    public void test_lockJJZ_NotOverlapping() throws Exception {
+        final long POSITION = 100;
+        final long SIZE = 200;
+        FileLock fileLock1 = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+        assertTrue(fileLock1.isValid());
+        FileLock fileLock2 = writeOnlyFileChannel.lock(POSITION + SIZE, SIZE,
+                false);
+        assertTrue(fileLock2.isValid());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#lock(long,long,boolean)
+     */
+    public void test_lockJJZ_After_Release() throws Exception {
+        fileLock = writeOnlyFileChannel.lock(0, 10, false);
+        fileLock.release();
+        // after release file lock can be obtained again.
+        fileLock = writeOnlyFileChannel.lock(0, 10, false);
+        assertTrue(fileLock.isValid());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock()
+     */
+    public void test_tryLock() throws Exception {
+        MockFileChannel mockFileChannel = new MockFileChannel();
+        // Verify that calling tryLock() leads to the method
+        // tryLock(long, long, boolean) being called with a 0 for the
+        // first parameter, Long.MAX_VALUE as the second parameter and false
+        // as the third parameter.
+        mockFileChannel.tryLock();
+        assertTrue(mockFileChannel.isTryLockCalled);
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     */
+    public void test_tryLockJJZ_Closed() throws Exception {
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.tryLock(0, 10, false);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.tryLock(0, 10, false);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.tryLock(0, 10, false);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        // throws ClosedChannelException before IllegalArgumentException
+        try {
+            readWriteFileChannel.tryLock(-1, 0, false);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     */
+    public void test_tryLockJJZ_IllegalArgument() throws Exception {
+        try {
+            writeOnlyFileChannel.tryLock(0, -1, false);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            writeOnlyFileChannel.tryLock(-1, 0, false);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.tryLock(-1, -1, false);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.tryLock(Long.MAX_VALUE, 1, false);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     */
+    public void test_tryLockJJZ_NonWritable() throws Exception {
+        try {
+            readOnlyFileChannel.tryLock(0, 10, false);
+            fail("should throw NonWritableChannelException");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+
+        // throws NonWritableChannelException before IllegalArgumentException
+        try {
+            readOnlyFileChannel.tryLock(-1, 0, false);
+            fail("should throw NonWritableChannelException");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     */
+    public void test_tryLockJJZ_NonReadable() throws Exception {
+        try {
+            writeOnlyFileChannel.tryLock(0, 10, true);
+            fail("should throw NonReadableChannelException");
+        } catch (NonReadableChannelException e) {
+            // expected
+        }
+
+        // throws NonReadableChannelException before IllegalArgumentException
+        try {
+            writeOnlyFileChannel.tryLock(-1, 0, true);
+            fail("should throw NonReadableChannelException");
+        } catch (NonReadableChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     */
+    public void test_tryLockJJZ_Shared() throws Exception {
+        final long POSITION = 100;
+        final long SIZE = 200;
+        fileLock = readOnlyFileChannel.tryLock(POSITION, SIZE, true);
+        assertTrue(fileLock.isValid());
+        // fileLock.isShared depends on whether the underlying platform support
+        // shared lock, but it works on Windows & Linux.
+        assertTrue(fileLock.isShared());
+        assertSame(readOnlyFileChannel, fileLock.channel());
+        assertEquals(POSITION, fileLock.position());
+        assertEquals(SIZE, fileLock.size());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     */
+    public void test_tryLockJJZ_NotShared() throws Exception {
+        final long POSITION = 100;
+        final long SIZE = 200;
+        fileLock = writeOnlyFileChannel.tryLock(POSITION, SIZE, false);
+        assertTrue(fileLock.isValid());
+        assertFalse(fileLock.isShared());
+        assertSame(writeOnlyFileChannel, fileLock.channel());
+        assertEquals(POSITION, fileLock.position());
+        assertEquals(SIZE, fileLock.size());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     */
+    public void test_tryLockJJZ_Long_MAX_VALUE() throws Exception {
+        final long POSITION = 0;
+        final long SIZE = Long.MAX_VALUE;
+        fileLock = readOnlyFileChannel.tryLock(POSITION, SIZE, true);
+        assertTrue(fileLock.isValid());
+        assertTrue(fileLock.isShared());
+        assertEquals(POSITION, fileLock.position());
+        assertEquals(SIZE, fileLock.size());
+        assertSame(readOnlyFileChannel, fileLock.channel());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     */
+    public void test_tryLockJJZ_Overlapping() throws Exception {
+        final long POSITION = 100;
+        final long SIZE = 200;
+        fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+        assertTrue(fileLock.isValid());
+
+        try {
+            writeOnlyFileChannel.lock(POSITION + 1, SIZE, false);
+            fail("should throw OverlappingFileLockException");
+        } catch (OverlappingFileLockException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+     */
+    public void test_tryLockJJZ_NotOverlapping() throws Exception {
+        final long POSITION = 100;
+        final long SIZE = 200;
+        FileLock fileLock1 = writeOnlyFileChannel
+                .tryLock(POSITION, SIZE, false);
+        assertTrue(fileLock1.isValid());
+
+        FileLock fileLock2 = writeOnlyFileChannel.tryLock(POSITION + SIZE,
+                SIZE, false);
+        assertTrue(fileLock2.isValid());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#tryLock(long,long,boolean)
+     */
+    public void test_tryLockJJZ_After_Release() throws Exception {
+        fileLock = writeOnlyFileChannel.tryLock(0, 10, false);
+        fileLock.release();
+
+        // after release file lock can be obtained again.
+        fileLock = writeOnlyFileChannel.tryLock(0, 10, false);
+        assertTrue(fileLock.isValid());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+     */
+    public void test_readLByteBuffer_Null() throws Exception {
+        ByteBuffer readBuffer = null;
+
+        try {
+            readOnlyFileChannel.read(readBuffer);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.read(readBuffer);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+     */
+    public void test_readLByteBuffer_Closed() throws Exception {
+        ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.read(readBuffer);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.read(readBuffer);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.read(readBuffer);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        // should throw ClosedChannelException first
+        readBuffer = null;
+        try {
+            readWriteFileChannel.read(readBuffer);
+            fail();
+        } catch (ClosedChannelException expected) {
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void test_readLByteBuffer_WriteOnly() throws Exception {
+        ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+        try {
+            writeOnlyFileChannel.read(readBuffer);
+            fail();
+        } catch (NonReadableChannelException expected) {
+        }
+
+        readBuffer = null;
+        try {
+            writeOnlyFileChannel.read(readBuffer);
+            fail();
+        } catch (NonReadableChannelException expected) {
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void test_readLByteBuffer_EmptyFile() throws Exception {
+        ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+        int result = readOnlyFileChannel.read(readBuffer);
+        assertEquals(-1, result);
+        assertEquals(0, readBuffer.position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+     */
+    public void test_readLByteBuffer_LimitedCapacity() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+
+        ByteBuffer readBuffer = ByteBuffer.allocate(LIMITED_CAPACITY);
+        int result = readOnlyFileChannel.read(readBuffer);
+        assertEquals(LIMITED_CAPACITY, result);
+        assertEquals(LIMITED_CAPACITY, readBuffer.position());
+        readBuffer.flip();
+        for (int i = 0; i < LIMITED_CAPACITY; i++) {
+            assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+        }
+    }
+
+    public void test_readLByteBuffer() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+
+        ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_AS_BYTES_LENGTH);
+        int result = readOnlyFileChannel.read(readBuffer);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, readBuffer.position());
+        readBuffer.flip();
+        for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+            assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+        }
+    }
+
+    public void test_readLByteBufferJ_Null() throws Exception {
+        try {
+            readOnlyFileChannel.read(null, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            readWriteFileChannel.read(null, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void test_readLByteBufferJ_Closed() throws Exception {
+        ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.read(readBuffer, 0);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.read(readBuffer, 0);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    public void test_readLByteBufferJ_IllegalArgument() throws Exception {
+        ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+        try {
+            readOnlyFileChannel.read(readBuffer, -1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            writeOnlyFileChannel.read(readBuffer, -1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            readWriteFileChannel.read(readBuffer, -1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void test_readLByteBufferJ_WriteOnly() throws Exception {
+        ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+        try {
+            writeOnlyFileChannel.read(readBuffer, 0);
+            fail();
+        } catch (NonReadableChannelException expected) {
+        }
+    }
+
+    public void test_readLByteBufferJ_Emptyfile() throws Exception {
+        ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+        int result = readOnlyFileChannel.read(readBuffer, 0);
+        assertEquals(-1, result);
+        assertEquals(0, readBuffer.position());
+    }
+
+    public void test_readLByteBufferJ_Position_BeyondFileLimit() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+
+        ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+        int result = readOnlyFileChannel.read(readBuffer,
+                CONTENT_AS_BYTES.length);
+        assertEquals(-1, result);
+        assertEquals(0, readBuffer.position());
+    }
+
+    public void test_readLByteBufferJ_Position_As_Long() throws Exception {
+        ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+        try {
+            readOnlyFileChannel.read(readBuffer, Long.MAX_VALUE);
+        } catch (IOException expected) {
+        }
+    }
+
+    public void test_readLByteBufferJ() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+        final int BUFFER_POSITION = 1;
+        readBuffer.position(BUFFER_POSITION);
+
+        final int POSITION = 2;
+        int result = readOnlyFileChannel.read(readBuffer, POSITION);
+        assertEquals(CONTENT_AS_BYTES_LENGTH - POSITION, result);
+        assertEquals(BUFFER_POSITION + result, readBuffer.position());
+
+        readBuffer.flip();
+        readBuffer.position(BUFFER_POSITION);
+        for (int i = POSITION; i < CONTENT_AS_BYTES_LENGTH; i++) {
+            assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[])
+     */
+    public void test_read$LByteBuffer() throws Exception {
+        // regression test for Harmony-849
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        ByteBuffer[] readBuffers = new ByteBuffer[2];
+        readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+        readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+        long readCount = readOnlyFileChannel.read(readBuffers);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, readCount);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, readBuffers[0].position());
+        assertEquals(0, readBuffers[1].position());
+        readBuffers[0].flip();
+        for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+            assertEquals(CONTENT_AS_BYTES[i], readBuffers[0].get());
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[])
+     */
+    public void test_read$LByteBuffer_mock() throws Exception {
+        FileChannel mockChannel = new MockFileChannel();
+        ByteBuffer[] buffers = new ByteBuffer[2];
+        mockChannel.read(buffers);
+        // Verify that calling read(ByteBuffer[] dsts) leads to the method
+        // read(dsts, 0, dsts.length)
+        assertTrue(((MockFileChannel)mockChannel).isReadCalled);
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read$LByteBufferII_Null() throws Exception {
+        ByteBuffer[] readBuffers = null;
+
+        try {
+            readOnlyFileChannel.read(readBuffers, 0, 1);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            readOnlyFileChannel.read(readBuffers, 1, 11);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            writeOnlyFileChannel.read(readBuffers, 0, 1);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.read(readBuffers, 0, 1);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // first throws NullPointerException
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.read(readBuffers, 0, 1);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read$LByteBufferII_Closed() throws Exception {
+        ByteBuffer[] readBuffers = new ByteBuffer[2];
+        readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.read(readBuffers, 0, 1);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.read(readBuffers, 0, 1);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.read(readBuffers, 0, 1);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        // regression test for Harmony-902
+        readBuffers[0] = null;
+        try {
+            readOnlyFileChannel.read(readBuffers, 0, 1);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+        try {
+            writeOnlyFileChannel.read(readBuffers, 0, 1);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+        try {
+            readWriteFileChannel.read(readBuffers, 0, 1);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read$LByteBufferII_WriteOnly() throws Exception {
+        ByteBuffer[] readBuffers = new ByteBuffer[2];
+        readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+
+        try {
+            writeOnlyFileChannel.read(readBuffers, 0, 1);
+            fail("should throw NonReadableChannelException");
+        } catch (NonReadableChannelException e) {
+            // expected
+        }
+
+        // first throws NonReadableChannelException.
+        readBuffers[0] = null;
+        try {
+            writeOnlyFileChannel.read(readBuffers, 0, 1);
+            fail("should throw NonReadableChannelException");
+        } catch (NonReadableChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read$LByteBufferII_IndexOutOfBound() throws Exception {
+        ByteBuffer[] readBuffers = new ByteBuffer[2];
+        readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+        readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+        try {
+            readOnlyFileChannel.read(readBuffers, 2, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+
+        try {
+            readWriteFileChannel.read(null, -1, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            writeOnlyFileChannel.read(readBuffers, 0, 3);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+
+        try {
+            readWriteFileChannel.read(readBuffers, -1, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.read(readBuffers, 0, 3);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read$LByteBufferII_EmptyFile() throws Exception {
+        ByteBuffer[] readBuffers = new ByteBuffer[2];
+        readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+        readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+        long result = readOnlyFileChannel.read(readBuffers, 0, 2);
+        assertEquals(-1, result);
+        assertEquals(0, readBuffers[0].position());
+        assertEquals(0, readBuffers[1].position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read$LByteBufferII_EmptyBuffers() throws Exception {
+        ByteBuffer[] readBuffers = new ByteBuffer[2];
+        try {
+            readOnlyFileChannel.read(readBuffers, 0, 2);
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+        try {
+            readOnlyFileChannel.read(readBuffers, 0, 2);
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        long result = readOnlyFileChannel.read(readBuffers, 0, 1);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read$LByteBufferII_EmptyFile_EmptyBuffers()
+            throws Exception {
+        ByteBuffer[] readBuffers = new ByteBuffer[2];
+        // will not throw NullPointerException
+        long result = readOnlyFileChannel.read(readBuffers, 0, 0);
+        assertEquals(0, result);
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read$LByteBufferII_Length_Zero() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        ByteBuffer[] readBuffers = new ByteBuffer[2];
+        readBuffers[0] = ByteBuffer.allocate(LIMITED_CAPACITY);
+        readBuffers[1] = ByteBuffer.allocate(LIMITED_CAPACITY);
+        long result = readOnlyFileChannel.read(readBuffers, 1, 0);
+        assertEquals(0, result);
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read$LByteBufferII_LimitedCapacity() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        ByteBuffer[] readBuffers = new ByteBuffer[2];
+        readBuffers[0] = ByteBuffer.allocate(LIMITED_CAPACITY);
+        readBuffers[1] = ByteBuffer.allocate(LIMITED_CAPACITY);
+
+        // reads to the second buffer
+        long result = readOnlyFileChannel.read(readBuffers, 1, 1);
+        assertEquals(LIMITED_CAPACITY, result);
+        assertEquals(0, readBuffers[0].position());
+        assertEquals(LIMITED_CAPACITY, readBuffers[1].position());
+
+        readBuffers[1].flip();
+        for (int i = 0; i < LIMITED_CAPACITY; i++) {
+            assertEquals(CONTENT_AS_BYTES[i], readBuffers[1].get());
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read$LByteBufferII() throws Exception {
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        ByteBuffer[] readBuffers = new ByteBuffer[2];
+        readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+        readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+        // writes to the second buffer
+        assertEquals(CONTENT_AS_BYTES_LENGTH, readOnlyFileChannel.read(
+                readBuffers, 1, 1));
+        assertEquals(0, readBuffers[0].position());
+        assertEquals(CONTENT_AS_BYTES_LENGTH, readBuffers[1].position());
+
+        readBuffers[1].flip();
+        for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+            assertEquals(CONTENT_AS_BYTES[i], readBuffers[1].get());
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#isOpen()
+     */
+    public void test_isOpen() throws Exception {
+        // Regression for HARMONY-40
+        File logFile = File.createTempFile("out", "tmp");
+        logFile.deleteOnExit();
+        FileOutputStream out = new FileOutputStream(logFile, true);
+        FileChannel channel = out.getChannel();
+        out.write(1);
+        out.close();
+        assertFalse("Assert 0: Channel is still open", channel.isOpen());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#position()
+     */
+    public void test_position_append() throws Exception {
+        // Regression test for Harmony-508
+        File tmpfile = File.createTempFile("FileOutputStream", "tmp");
+        tmpfile.deleteOnExit();
+        FileOutputStream fos = new FileOutputStream(tmpfile);
+        byte[] b = new byte[10];
+        for (int i = 0; i < b.length; i++) {
+            b[i] = (byte) i;
+        }
+        fos.write(b);
+        fos.flush();
+        fos.close();
+        FileOutputStream f = new FileOutputStream(tmpfile, true);
+        // Harmony expected 10, but the RI and Android report 0.
+        assertEquals(0, f.getChannel().position());
+    }
+
+
+    /**
+     * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+     */
+    public void test_map_AbnormalMode() throws IOException {
+        try {
+            writeOnlyFileChannel.map(MapMode.READ_ONLY, 0, CONTENT_LENGTH);
+            fail("should throw NonReadableChannelException.");
+        } catch (NonReadableChannelException ex) {
+            // expected;
+        }
+        try {
+            writeOnlyFileChannel.map(MapMode.READ_WRITE, 0, CONTENT_LENGTH);
+            fail("should throw NonReadableChannelException.");
+        } catch (NonReadableChannelException ex) {
+            // expected;
+        }
+        try {
+            writeOnlyFileChannel.map(MapMode.PRIVATE, 0, CONTENT_LENGTH);
+            fail("should throw NonReadableChannelException.");
+        } catch (NonReadableChannelException ex) {
+            // expected;
+        }
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.map(MapMode.READ_WRITE, 0, -1);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException ex) {
+            // expected;
+        }
+
+        try {
+            readOnlyFileChannel.map(MapMode.READ_WRITE, 0, CONTENT_LENGTH);
+            fail("should throw NonWritableChannelException .");
+        } catch (NonWritableChannelException ex) {
+            // expected;
+        }
+        try {
+            readOnlyFileChannel.map(MapMode.PRIVATE, 0, CONTENT_LENGTH);
+            fail("should throw NonWritableChannelException .");
+        } catch (NonWritableChannelException ex) {
+            // expected;
+        }
+        try {
+            readOnlyFileChannel.map(MapMode.READ_WRITE, -1, CONTENT_LENGTH);
+            fail("should throw IAE.");
+        } catch (IllegalArgumentException ex) {
+            // expected;
+        }
+        try {
+            readOnlyFileChannel.map(MapMode.READ_WRITE, 0, -1);
+            fail("should throw IAE.");
+        } catch (IllegalArgumentException ex) {
+            // expected;
+        }
+
+        try {
+            readOnlyFileChannel.map(MapMode.READ_ONLY, 0, CONTENT_LENGTH + 1);
+            fail();
+        } catch (NonWritableChannelException expected) {
+        } catch (IOException expected) {
+        }
+        try {
+            readOnlyFileChannel.map(MapMode.READ_ONLY, 2, CONTENT_LENGTH - 1);
+            fail();
+        } catch (NonWritableChannelException expected) {
+        } catch (IOException expected) {
+        }
+
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.map(MapMode.READ_WRITE, 0, -1);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException ex) {
+            // expected;
+        }
+        try {
+            readOnlyFileChannel.map(MapMode.READ_ONLY, 2, CONTENT_LENGTH - 1);
+            fail("should throw IOException.");
+        } catch (IOException ex) {
+            // expected;
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.map(MapMode.READ_WRITE, 0, -1);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException ex) {
+            // expected;
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+     */
+    public void test_map_ReadOnly_CloseChannel() throws IOException {
+        // close channel has no effect on map if mapped
+        assertEquals(0, readWriteFileChannel.size());
+        MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.READ_ONLY,
+                0, CONTENT_LENGTH);
+        assertEquals(CONTENT_LENGTH, readWriteFileChannel.size());
+        readOnlyFileChannel.close();
+        assertEquals(CONTENT_LENGTH, mapped.limit());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+     */
+    public void test_map_Private_CloseChannel() throws IOException {
+        MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.PRIVATE, 0,
+                CONTENT_LENGTH);
+        readWriteFileChannel.close();
+        mapped.put(TEST_BYTES);
+        assertEquals(CONTENT_LENGTH, mapped.limit());
+        assertEquals("test".length(), mapped.position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+     */
+    public void test_map_ReadOnly() throws IOException {
+        MappedByteBuffer mapped = null;
+        // try put something to readonly map
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        mapped = readOnlyFileChannel.map(MapMode.READ_ONLY, 0, CONTENT_LENGTH);
+        try {
+            mapped.put(TEST_BYTES);
+            fail("should throw ReadOnlyBufferException.");
+        } catch (ReadOnlyBufferException ex) {
+            // expected;
+        }
+        assertEquals(CONTENT_LENGTH, mapped.limit());
+        assertEquals(CONTENT_LENGTH, mapped.capacity());
+        assertEquals(0, mapped.position());
+
+        // try to get a readonly map from read/write channel
+        writeDataToFile(fileOfReadWriteFileChannel);
+        mapped = readWriteFileChannel.map(MapMode.READ_ONLY, 0, CONTENT
+                .length());
+        assertEquals(CONTENT_LENGTH, mapped.limit());
+        assertEquals(CONTENT_LENGTH, mapped.capacity());
+        assertEquals(0, mapped.position());
+
+        // map not change channel's position
+        assertEquals(0, readOnlyFileChannel.position());
+        assertEquals(0, readWriteFileChannel.position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+     */
+    public void test_map_ReadOnly_NonZeroPosition() throws IOException {
+        this.writeDataToFile(fileOfReadOnlyFileChannel);
+        MappedByteBuffer mapped = readOnlyFileChannel.map(MapMode.READ_ONLY,
+                10, CONTENT_LENGTH - 10);
+        assertEquals(CONTENT_LENGTH - 10, mapped.limit());
+        assertEquals(CONTENT_LENGTH - 10, mapped.capacity());
+        assertEquals(0, mapped.position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+     */
+    public void test_map_Private() throws IOException {
+        this.writeDataToFile(fileOfReadWriteFileChannel);
+        MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.PRIVATE, 0,
+                CONTENT_LENGTH);
+        assertEquals(CONTENT_LENGTH, mapped.limit());
+        // test copy on write if private
+        ByteBuffer returnByPut = mapped.put(TEST_BYTES);
+        assertSame(returnByPut, mapped);
+        ByteBuffer checkBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+        mapped.force();
+        readWriteFileChannel.read(checkBuffer);
+        assertEquals(CONTENT, new String(checkBuffer.array(), "iso8859-1"));
+
+        // test overflow
+        try {
+            mapped.put(("test" + CONTENT).getBytes("iso8859-1"));
+            fail("should throw BufferOverflowException.");
+        } catch (BufferOverflowException ex) {
+            // expected;
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+     */
+    public void test_map_Private_NonZeroPosition() throws IOException {
+        MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.PRIVATE, 10,
+                CONTENT_LENGTH - 10);
+        assertEquals(CONTENT_LENGTH - 10, mapped.limit());
+        assertEquals(CONTENT_LENGTH - 10, mapped.capacity());
+        assertEquals(0, mapped.position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+     */
+    public void test_map_ReadWrite() throws IOException {
+        MappedByteBuffer mapped = null;
+        writeDataToFile(fileOfReadWriteFileChannel);
+        mapped = readWriteFileChannel.map(MapMode.READ_WRITE, 0, CONTENT
+                .length());
+
+        // put something will change its channel
+        ByteBuffer returnByPut = mapped.put(TEST_BYTES);
+        assertSame(returnByPut, mapped);
+        String checkString = "test" + CONTENT.substring(4);
+        ByteBuffer checkBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+        mapped.force();
+        readWriteFileChannel.position(0);
+        readWriteFileChannel.read(checkBuffer);
+        assertEquals(checkString, new String(checkBuffer.array(), "iso8859-1"));
+
+        try {
+            mapped.put(("test" + CONTENT).getBytes("iso8859-1"));
+            fail("should throw BufferOverflowException.");
+        } catch (BufferOverflowException ex) {
+            // expected;
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+     */
+    public void test_map_ReadWrite_NonZeroPosition() throws IOException {
+        // test position non-zero
+        writeDataToFile(fileOfReadWriteFileChannel);
+        MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.READ_WRITE,
+                10, CONTENT_LENGTH - 10);
+        assertEquals(CONTENT_LENGTH - 10, mapped.limit());
+        assertEquals(CONTENT.length() - 10, mapped.capacity());
+        assertEquals(0, mapped.position());
+        mapped.put(TEST_BYTES);
+        ByteBuffer checkBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+        readWriteFileChannel.read(checkBuffer);
+        String expected = CONTENT.substring(0, 10) + "test"
+                + CONTENT.substring(10 + "test".length());
+        assertEquals(expected, new String(checkBuffer.array(), "iso8859-1"));
+    }
+
+    /**
+     * Tests map() method for the value of positions exceeding memory
+     * page size and allocation granularity size.
+     *
+     * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+     */
+    public void test_map_LargePosition() throws IOException {
+        // Regression test for HARMONY-3085
+        int[] sizes = {
+            4096, // 4K size (normal page size for Linux & Windows)
+            65536, // 64K size (alocation granularity size for Windows)
+        };
+        final int CONTENT_LEN = 10;
+
+        for (int i = 0; i < sizes.length; ++i) {
+            // reset the file and the channel for the iterations
+            // (for the first iteration it was done by setUp()
+            if (i > 0 ) {
+                fileOfReadOnlyFileChannel = File.createTempFile(
+                        "File_of_readOnlyFileChannel", "tmp");
+                fileOfReadOnlyFileChannel.deleteOnExit();
+                readOnlyFileChannel = new FileInputStream(fileOfReadOnlyFileChannel)
+                        .getChannel();
+            }
+
+            writeLargeDataToFile(fileOfReadOnlyFileChannel, sizes[i] + 2 * CONTENT_LEN);
+            MappedByteBuffer mapped = readOnlyFileChannel.map(MapMode.READ_ONLY,
+                    sizes[i], CONTENT_LEN);
+            assertEquals("Incorrectly mapped file channel for " + sizes[i]
+                    + " position (capacity)", CONTENT_LEN, mapped.capacity());
+            assertEquals("Incorrectly mapped file channel for " + sizes[i]
+                    + " position (limit)", CONTENT_LEN, mapped.limit());
+            assertEquals("Incorrectly mapped file channel for " + sizes[i]
+                    + " position (position)", 0, mapped.position());
+
+            // map not change channel's position
+            assertEquals(0, readOnlyFileChannel.position());
+
+            // Close the file and the channel before the next iteration
+            readOnlyFileChannel.close();
+            fileOfReadOnlyFileChannel.delete();
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+     */
+    public void test_writeLByteBuffer_Null() throws Exception {
+        ByteBuffer writeBuffer = null;
+
+        try {
+            writeOnlyFileChannel.write(writeBuffer);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.write(writeBuffer);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+     */
+    public void test_writeLByteBuffer_Closed() throws Exception {
+        ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.write(writeBuffer);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.write(writeBuffer);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.write(writeBuffer);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+
+        writeBuffer = null;
+        try {
+            readWriteFileChannel.read(writeBuffer);
+            fail();
+        } catch (NullPointerException expected) {
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+     */
+    public void test_writeLByteBuffer_ReadOnly() throws Exception {
+        ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+        try {
+            readOnlyFileChannel.write(writeBuffer);
+            fail("should throw NonWritableChannelException");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+
+        // first throws NonWriteableChannelException
+        writeBuffer = null;
+        try {
+            readOnlyFileChannel.write(writeBuffer);
+            fail("should throw NonWritableChannelException");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+     */
+    public void test_writeLByteBuffer() throws Exception {
+        ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+
+        int result = writeOnlyFileChannel.write(writeBuffer);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffer.position());
+        writeOnlyFileChannel.close();
+
+        assertEquals(CONTENT_AS_BYTES_LENGTH, fileOfWriteOnlyFileChannel
+                .length());
+
+        fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+        byte[] inputBuffer = new byte[CONTENT_AS_BYTES_LENGTH];
+        fis.read(inputBuffer);
+        assertTrue(Arrays.equals(CONTENT_AS_BYTES, inputBuffer));
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+     */
+    public void test_writeLByteBuffer_positioned() throws Exception {
+        final int pos = 5;
+        ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+        writeBuffer.position(pos);
+        int result = writeOnlyFileChannel.write(writeBuffer);
+        assertEquals(CONTENT_AS_BYTES_LENGTH - pos, result);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffer.position());
+        writeOnlyFileChannel.close();
+
+        assertEquals(CONTENT_AS_BYTES_LENGTH - pos, fileOfWriteOnlyFileChannel
+                .length());
+
+        fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+        byte[] inputBuffer = new byte[CONTENT_AS_BYTES_LENGTH - pos];
+        fis.read(inputBuffer);
+        String test = CONTENT.substring(pos);
+        assertTrue(Arrays.equals(test.getBytes("iso8859-1"), inputBuffer));
+    }
+
+    public void test_writeLByteBufferJ_Null() throws Exception {
+        try {
+            readWriteFileChannel.write(null, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        } catch (NonWritableChannelException expected) {
+        }
+
+        try {
+            writeOnlyFileChannel.write(null, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            readWriteFileChannel.write(null, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void test_writeLByteBufferJ_Closed() throws Exception {
+        ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.write(writeBuffer, 0);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.write(writeBuffer, 0);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    public void test_writeLByteBufferJ_ReadOnly() throws Exception {
+        ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+        try {
+            readOnlyFileChannel.write(writeBuffer, 10);
+            fail();
+        } catch (NonWritableChannelException expected) {
+        }
+    }
+
+    public void test_writeLByteBufferJ_IllegalArgument() throws Exception {
+        ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+        try {
+            readOnlyFileChannel.write(writeBuffer, -1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            writeOnlyFileChannel.write(writeBuffer, -1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            readWriteFileChannel.write(writeBuffer, -1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer,long)
+     */
+    public void test_writeLByteBufferJ() throws Exception {
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        final int POSITION = 4;
+        ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+        int result = writeOnlyFileChannel.write(writeBuffer, POSITION);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffer.position());
+        writeOnlyFileChannel.close();
+
+        assertEquals(POSITION + CONTENT_AS_BYTES_LENGTH,
+                fileOfWriteOnlyFileChannel.length());
+
+        fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+        byte[] inputBuffer = new byte[POSITION + CONTENT_AS_BYTES_LENGTH];
+        fis.read(inputBuffer);
+        byte[] expectedResult = new byte[POSITION + CONTENT_AS_BYTES_LENGTH];
+        System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, 0, POSITION);
+        System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, POSITION,
+                CONTENT_AS_BYTES_LENGTH);
+        assertTrue(Arrays.equals(expectedResult, inputBuffer));
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer[])
+     */
+    public void test_write$LByteBuffer() throws Exception {
+        ByteBuffer[] writeBuffers = new ByteBuffer[2];
+        MockFileChannel mockFileChannel = new MockFileChannel();
+        mockFileChannel.write(writeBuffers);
+        // verify that calling write(ByteBuffer[] srcs) leads to the method
+        // write(srcs, 0, srcs.length)
+        assertTrue(mockFileChannel.isWriteCalled);
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+     */
+    public void test_write$LByteBufferII_Null() throws Exception {
+        ByteBuffer[] writeBuffers = null;
+
+        try {
+            readOnlyFileChannel.write(writeBuffers, 1, 2);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            writeOnlyFileChannel.write(writeBuffers, 1, 2);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.write(writeBuffers, 1, 2);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // first throws NullPointerException
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.write(writeBuffers, 0, 0);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+     */
+    public void test_write$LByteBufferII_Closed() throws Exception {
+        ByteBuffer[] writeBuffers = new ByteBuffer[2];
+        writeBuffers[0] = ByteBuffer.allocate(CAPACITY);
+        writeBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.write(writeBuffers, 0, 2);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.write(writeBuffers, 0, 2);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.write(writeBuffers, 0, 2);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        // throws ClosedChannelException first
+        writeBuffers[0] = null;
+        try {
+            readWriteFileChannel.write(writeBuffers, 0, 2);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+     */
+    public void test_write$LByteBufferII_ReadOnly() throws Exception {
+        ByteBuffer[] writeBuffers = new ByteBuffer[2];
+        writeBuffers[0] = ByteBuffer.allocate(CAPACITY);
+        writeBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+        try {
+            readOnlyFileChannel.write(writeBuffers, 0, 2);
+            fail();
+        } catch (NonWritableChannelException e) {
+        }
+
+        try {
+            readOnlyFileChannel.write(writeBuffers, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+
+        writeBuffers = null;
+        try {
+            readOnlyFileChannel.write(writeBuffers, 0, 1);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        readOnlyFileChannel.close();
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+     */
+    public void test_write$LByteBufferII_EmptyBuffers() throws Exception {
+        ByteBuffer[] writeBuffers = new ByteBuffer[2];
+        try {
+            writeOnlyFileChannel.write(writeBuffers, 0, 2);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.write(writeBuffers, 0, 2);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+     */
+    public void test_write$LByteBufferII() throws Exception {
+        ByteBuffer[] writeBuffers = new ByteBuffer[2];
+        writeBuffers[0] = ByteBuffer.wrap(CONTENT_AS_BYTES);
+        writeBuffers[1] = ByteBuffer.wrap(CONTENT_AS_BYTES);
+
+        long result = writeOnlyFileChannel.write(writeBuffers, 0, 2);
+        assertEquals(CONTENT_AS_BYTES_LENGTH * 2, result);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffers[0].position());
+        assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffers[1].position());
+        writeOnlyFileChannel.close();
+
+        assertEquals(CONTENT_AS_BYTES_LENGTH * 2, fileOfWriteOnlyFileChannel
+                .length());
+
+        fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+        byte[] inputBuffer = new byte[CONTENT_AS_BYTES_LENGTH];
+        fis.read(inputBuffer);
+        byte[] expectedResult = new byte[CONTENT_AS_BYTES_LENGTH * 2];
+        System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, 0,
+                CONTENT_AS_BYTES_LENGTH);
+        System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult,
+                CONTENT_AS_BYTES_LENGTH, CONTENT_AS_BYTES_LENGTH);
+        assertTrue(Arrays.equals(CONTENT_AS_BYTES, inputBuffer));
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+     */
+    public void test_transferFromLReadableByteChannelJJ_Closed()
+            throws Exception {
+        readByteChannel = DatagramChannel.open();
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.transferFrom(readByteChannel, 0, 0);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.transferFrom(readByteChannel, 0, 10);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.transferFrom(readByteChannel, 0, 0);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        // should throw ClosedChannelException first.
+        try {
+            readWriteFileChannel.transferFrom(readByteChannel, 0, -1);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+     */
+    public void test_transferFromLReadableByteChannelJJ_SourceClosed()
+            throws Exception {
+        readByteChannel = DatagramChannel.open();
+        readByteChannel.close();
+
+        try {
+            readOnlyFileChannel.transferFrom(readByteChannel, 0, 10);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        try {
+            writeOnlyFileChannel.transferFrom(readByteChannel, 0, 10);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.transferFrom(readByteChannel, 0, 10);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        // should throw ClosedChannelException first.
+        try {
+            readWriteFileChannel.transferFrom(readByteChannel, 0, -1);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+     */
+    public void test_transferFromLReadableByteChannelJJ_IllegalArgument()
+            throws Exception {
+        readByteChannel = DatagramChannel.open();
+        try {
+            writeOnlyFileChannel.transferFrom(readByteChannel, 10, -1);
+            fail("should throw IllegalArgumentException.");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.transferFrom(readByteChannel, -1, -10);
+            fail("should throw IllegalArgumentException.");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+     */
+    public void test_transferFromLReadableByteChannelJJ_NonWritable()
+            throws Exception {
+        readByteChannel = DatagramChannel.open();
+        try {
+            readOnlyFileChannel.transferFrom(readByteChannel, 0, 0);
+            fail("should throw NonWritableChannelException.");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+     */
+    public void test_transferFromLReadableByteChannelJJ_SourceNonReadable()
+            throws Exception {
+        try {
+            readWriteFileChannel.transferFrom(writeOnlyFileChannel, 0, 0);
+            fail("should throw NonReadableChannelException.");
+        } catch (NonReadableChannelException e) {
+            // expected
+        }
+
+        // not throws NonReadableChannelException first if position beyond file
+        // size.
+        readWriteFileChannel.transferFrom(writeOnlyFileChannel, 10, 10);
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+     */
+    public void test_transferFromLReadableByteChannelJJ_PositionBeyondSize()
+            throws Exception {
+        // init data to file.
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        final int READONLYFILECHANNELPOSITION = 2;
+        readOnlyFileChannel.position(READONLYFILECHANNELPOSITION);
+
+        final int POSITION = CONTENT_AS_BYTES_LENGTH * 2;
+        final int LENGTH = 5;
+        long result = writeOnlyFileChannel.transferFrom(readOnlyFileChannel,
+                POSITION, LENGTH);
+        assertEquals(0, result);
+        assertEquals(0, writeOnlyFileChannel.position());
+        assertEquals(READONLYFILECHANNELPOSITION, readOnlyFileChannel
+                .position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+     */
+    public void test_transferFromLReadableByteChannelJJ_FileChannel()
+            throws Exception {
+        // init data to file.
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        final int READONLYFILECHANNELPOSITION = 2;
+        final int WRITEONLYFILECHANNELPOSITION = 4;
+        readOnlyFileChannel.position(READONLYFILECHANNELPOSITION);
+        writeOnlyFileChannel.position(WRITEONLYFILECHANNELPOSITION);
+
+        final int POSITION = 3;
+        final int LENGTH = 5;
+        long result = writeOnlyFileChannel.transferFrom(readOnlyFileChannel,
+                POSITION, LENGTH);
+        assertEquals(LENGTH, result);
+        assertEquals(WRITEONLYFILECHANNELPOSITION, writeOnlyFileChannel
+                .position());
+        assertEquals(READONLYFILECHANNELPOSITION + LENGTH, readOnlyFileChannel
+                .position());
+        writeOnlyFileChannel.close();
+
+        final int EXPECTED_LENGTH = POSITION + LENGTH;
+        fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+        byte[] resultContent = new byte[EXPECTED_LENGTH];
+        fis.read(resultContent);
+
+        byte[] expectedContent = new byte[EXPECTED_LENGTH];
+        System.arraycopy(CONTENT_AS_BYTES, 0, expectedContent, 0, POSITION);
+        System.arraycopy(CONTENT_AS_BYTES, READONLYFILECHANNELPOSITION,
+                expectedContent, POSITION, LENGTH);
+        assertTrue(Arrays.equals(expectedContent, resultContent));
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+     */
+    public void test_transferFromLReadableByteChannelJJ_DatagramChannel()
+            throws Exception {
+        // connects two datagramChannels.
+        datagramChannelReceiver = DatagramChannel.open();
+        datagramChannelReceiver.socket().bind(
+                new InetSocketAddress(InetAddress.getLocalHost(), 0));
+        datagramChannelSender = DatagramChannel.open();
+        datagramChannelSender.socket().bind(
+                new InetSocketAddress(InetAddress.getLocalHost(), 0));
+        datagramChannelReceiver.socket().setSoTimeout(TIME_OUT);
+        datagramChannelReceiver.connect(datagramChannelSender.socket()
+                .getLocalSocketAddress());
+        datagramChannelSender.socket().setSoTimeout(TIME_OUT);
+        ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+        datagramChannelSender.socket().setSoTimeout(TIME_OUT);
+        // sends data from datagramChannelSender to datagramChannelReceiver.
+        datagramChannelSender.send(writeBuffer, datagramChannelReceiver
+                .socket().getLocalSocketAddress());
+        datagramChannelReceiver.socket().setSoTimeout(TIME_OUT);
+
+        // transfers data from datagramChannelReceiver to fileChannel.
+        long result = writeOnlyFileChannel.transferFrom(
+                datagramChannelReceiver, 0, CONTENT_AS_BYTES_LENGTH);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+        assertEquals(0, writeOnlyFileChannel.position());
+        writeOnlyFileChannel.close();
+
+        // gets content from file.
+        fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, fileOfWriteOnlyFileChannel
+                .length());
+        byte[] resultContent = new byte[CONTENT_AS_BYTES_LENGTH];
+        fis.read(resultContent);
+
+        // compares contents.
+        assertTrue(Arrays.equals(CONTENT_AS_BYTES, resultContent));
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+     */
+    public void test_transferFromLReadableByteChannelJJ_SocketChannel()
+            throws Exception {
+        // connects two socketChannels.
+        socketChannelReceiver = SocketChannel.open();
+        serverSocketChannel = ServerSocketChannel.open();
+        serverSocketChannel.socket().bind(
+                new InetSocketAddress(InetAddress.getLocalHost(), 0));
+        socketChannelReceiver.socket().setSoTimeout(TIME_OUT);
+        socketChannelReceiver.connect(serverSocketChannel.socket()
+                .getLocalSocketAddress());
+        serverSocketChannel.socket().setSoTimeout(TIME_OUT);
+        socketChannelSender = serverSocketChannel.accept();
+        socketChannelSender.socket().setSoTimeout(TIME_OUT);
+
+        // sends data from socketChannelSender to socketChannelReceiver.
+        ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+        socketChannelSender.write(writeBuffer);
+
+        // transfers data from socketChannelReceiver to fileChannel.
+        long result = readWriteFileChannel.transferFrom(socketChannelReceiver,
+                0, CONTENT_AS_BYTES_LENGTH);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+        assertEquals(0, readWriteFileChannel.position());
+        readWriteFileChannel.close();
+
+        // gets content from file.
+        fis = new FileInputStream(fileOfReadWriteFileChannel);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, fileOfReadWriteFileChannel
+                .length());
+        byte[] resultContent = new byte[CONTENT_AS_BYTES_LENGTH];
+        fis.read(resultContent);
+
+        // compares content.
+        assertTrue(Arrays.equals(CONTENT_AS_BYTES, resultContent));
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+     */
+    public void test_transferFromLReadableByteChannelJJ_Pipe() throws Exception {
+        // inits data in file.
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        // inits pipe.
+        pipe = Pipe.open();
+
+        // writes content to pipe.
+        ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+        pipe.sink().write(writeBuffer);
+
+        // transfers data from pipe to fileChannel.
+        final int OFFSET = 2;
+        final int LENGTH = 4;
+        long result = writeOnlyFileChannel.transferFrom(pipe.source(), OFFSET,
+                LENGTH);
+        assertEquals(LENGTH, result);
+        writeOnlyFileChannel.close();
+
+        // gets content from file.
+        fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+        byte[] resultBytes = new byte[OFFSET + LENGTH];
+        fis.read(resultBytes);
+
+        // compares content.
+        byte[] expectedBytes = new byte[OFFSET + LENGTH];
+        System.arraycopy(CONTENT_AS_BYTES, 0, expectedBytes, 0, OFFSET);
+        System.arraycopy(CONTENT_AS_BYTES, 0, expectedBytes, OFFSET, LENGTH);
+
+        assertTrue(Arrays.equals(expectedBytes, resultBytes));
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+     */
+    public void test_transferToJJLWritableByteChannel_Null() throws Exception {
+        writableByteChannel = null;
+        try {
+            readOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+            fail();
+        } catch (NullPointerException expected) {
+        } catch (NonReadableChannelException expected) {
+        }
+
+        try {
+            readWriteFileChannel.transferTo(0, 10, writableByteChannel);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        readOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.transferTo(-1, 0, writableByteChannel);
+            fail();
+        } catch (NullPointerException expected) {
+        } catch (NonReadableChannelException expected) {
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+     */
+    public void test_transferToJJLWritableByteChannel_Closed() throws Exception {
+        writableByteChannel = DatagramChannel.open();
+        readOnlyFileChannel.close();
+        try {
+            readOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        writeOnlyFileChannel.close();
+        try {
+            writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        readWriteFileChannel.close();
+        try {
+            readWriteFileChannel.transferTo(0, 10, writableByteChannel);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        // should throw ClosedChannelException first.
+        try {
+            readWriteFileChannel.transferTo(0, -1, writableByteChannel);
+            fail("should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    public void test_transferToJJLWritableByteChannel_SourceClosed() throws Exception {
+        writableByteChannel = DatagramChannel.open();
+        writableByteChannel.close();
+
+        try {
+            readOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+
+        try {
+            writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+            fail();
+        } catch (ClosedChannelException expected) {
+        } catch (NonReadableChannelException expected) {
+        }
+
+        try {
+            readWriteFileChannel.transferTo(0, 10, writableByteChannel);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+
+        try {
+            readWriteFileChannel.transferTo(0, -1, writableByteChannel);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+     */
+    public void test_transferToJJLWritableByteChannel_IllegalArgument()
+            throws Exception {
+        writableByteChannel = DatagramChannel.open();
+        try {
+            readOnlyFileChannel.transferTo(10, -1, writableByteChannel);
+            fail("should throw IllegalArgumentException.");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.transferTo(-1, -10, writableByteChannel);
+            fail("should throw IllegalArgumentException.");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void test_transferToJJLWritableByteChannel_NonReadable() throws Exception {
+        writableByteChannel = DatagramChannel.open();
+        try {
+            writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+            fail();
+        } catch (NonReadableChannelException expected) {
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+     */
+    public void test_transferToJJLWritableByteChannel_TargetNonWritable()
+            throws Exception {
+        try {
+            readWriteFileChannel.transferTo(0, 0, readOnlyFileChannel);
+            fail("should throw NonWritableChannelException.");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+
+        // first throws NonWritableChannelException even position out of file
+        // size.
+        try {
+            readWriteFileChannel.transferTo(10, 10, readOnlyFileChannel);
+            fail("should throw NonWritableChannelException.");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+
+        // regression test for Harmony-941
+        // first throws NonWritableChannelException even arguments are illegal.
+        try {
+            readWriteFileChannel.transferTo(-1, 10, readOnlyFileChannel);
+            fail("should throw NonWritableChannelException.");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+
+        try {
+            readWriteFileChannel.transferTo(0, -1, readOnlyFileChannel);
+            fail("should throw NonWritableChannelException.");
+        } catch (NonWritableChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+     */
+    public void test_transferToJJLWritableByteChannel_PositionBeyondSize()
+            throws Exception {
+        // init data to file.
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        final int WRITEONLYFILECHANNELPOSITION = 2;
+        writeOnlyFileChannel.position(WRITEONLYFILECHANNELPOSITION);
+
+        final int POSITION = CONTENT_AS_BYTES_LENGTH * 2;
+        final int LENGTH = 5;
+        long result = readOnlyFileChannel.transferTo(POSITION, LENGTH,
+                writeOnlyFileChannel);
+        assertEquals(0, result);
+        assertEquals(0, readOnlyFileChannel.position());
+        assertEquals(WRITEONLYFILECHANNELPOSITION, writeOnlyFileChannel
+                .position());
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+     */
+    public void test_transferToJJLWritableByteChannel_FileChannel()
+            throws Exception {
+        // init data to file.
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        final int READONLYFILECHANNELPOSITION = 2;
+        final int WRITEONLYFILECHANNELPOSITION = 4;
+        readOnlyFileChannel.position(READONLYFILECHANNELPOSITION);
+        writeOnlyFileChannel.position(WRITEONLYFILECHANNELPOSITION);
+
+        final int POSITION = 3;
+        final int LENGTH = 5;
+        long result = readOnlyFileChannel.transferTo(POSITION, LENGTH,
+                writeOnlyFileChannel);
+        assertEquals(LENGTH, result);
+        assertEquals(READONLYFILECHANNELPOSITION, readOnlyFileChannel
+                .position());
+        assertEquals(WRITEONLYFILECHANNELPOSITION + LENGTH,
+                writeOnlyFileChannel.position());
+        writeOnlyFileChannel.close();
+
+        final int EXPECTED_LENGTH = WRITEONLYFILECHANNELPOSITION + LENGTH;
+        fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+        byte[] resultContent = new byte[EXPECTED_LENGTH];
+        fis.read(resultContent);
+
+        byte[] expectedContent = new byte[EXPECTED_LENGTH];
+        System.arraycopy(CONTENT_AS_BYTES, 0, expectedContent, 0,
+                WRITEONLYFILECHANNELPOSITION);
+        System.arraycopy(CONTENT_AS_BYTES, POSITION, expectedContent,
+                WRITEONLYFILECHANNELPOSITION, LENGTH);
+        assertTrue(Arrays.equals(expectedContent, resultContent));
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+     */
+    public void test_transferToJJLWritableByteChannel_SocketChannel()
+            throws Exception {
+        // inits data into file.
+        writeDataToFile(fileOfReadOnlyFileChannel);
+
+        // connects two socketChannels.
+        socketChannelReceiver = SocketChannel.open();
+        socketChannelReceiver.socket().bind(
+                new InetSocketAddress(InetAddress.getLocalHost(), 0));
+        serverSocketChannel = ServerSocketChannel.open();
+        serverSocketChannel.socket().bind(
+                new InetSocketAddress(InetAddress.getLocalHost(), 0));
+        socketChannelReceiver.socket().setSoTimeout(TIME_OUT);
+        socketChannelReceiver.connect(serverSocketChannel.socket()
+                .getLocalSocketAddress());
+        serverSocketChannel.socket().setSoTimeout(TIME_OUT);
+        socketChannelSender = serverSocketChannel.accept();
+        socketChannelSender.socket().setSoTimeout(TIME_OUT);
+
+        // position here should have no effect on transferTo since it uses
+        // offset from file_begin
+        final int POSITION = 10;
+        readOnlyFileChannel.position(POSITION);
+
+        // transfers data from file to socketChannelSender.
+        final int OFFSET = 2;
+        long result = readOnlyFileChannel.transferTo(OFFSET,
+                CONTENT_AS_BYTES_LENGTH * 2, socketChannelSender);
+        final int LENGTH = CONTENT_AS_BYTES_LENGTH - OFFSET;
+        assertEquals(LENGTH, result);
+        assertEquals(POSITION, readOnlyFileChannel.position());
+        readOnlyFileChannel.close();
+        socketChannelSender.close();
+
+        // gets contents from socketChannelReceiver.
+        ByteBuffer readBuffer = ByteBuffer.allocate(LENGTH + 1);
+        int totalRead = 0;
+        int countRead = 0;
+        long beginTime = System.currentTimeMillis();
+        while ((countRead = socketChannelReceiver.read(readBuffer)) != -1) {
+            totalRead += countRead;
+            // TIMEOUT
+            if (System.currentTimeMillis() - beginTime > TIME_OUT) {
+                break;
+            }
+        }
+        assertEquals(LENGTH, totalRead);
+
+        // compares contents.
+        readBuffer.flip();
+        for (int i = OFFSET; i < CONTENT_AS_BYTES_LENGTH; i++) {
+            assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+     */
+    public void test_transferToJJLWritableByteChannel_DatagramChannel()
+            throws Exception {
+        // inits data to file.
+        writeDataToFile(fileOfReadOnlyFileChannel);
+
+        // connects two datagramChannel
+        datagramChannelReceiver = DatagramChannel.open();
+        datagramChannelReceiver.socket().bind(
+                new InetSocketAddress(InetAddress.getLocalHost(), 0));
+        datagramChannelSender = DatagramChannel.open();
+        datagramChannelSender.socket().bind(
+                new InetSocketAddress(InetAddress.getLocalHost(), 0));
+        datagramChannelSender.socket().setSoTimeout(TIME_OUT);
+        datagramChannelSender.connect(datagramChannelReceiver.socket()
+                .getLocalSocketAddress());
+        datagramChannelReceiver.socket().setSoTimeout(TIME_OUT);
+        datagramChannelReceiver.connect(datagramChannelSender.socket()
+                .getLocalSocketAddress());
+
+        // transfers data from fileChannel to datagramChannelSender
+        long result = readOnlyFileChannel.transferTo(0,
+                CONTENT_AS_BYTES_LENGTH, datagramChannelSender);
+        assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+        assertEquals(0, readOnlyFileChannel.position());
+        readOnlyFileChannel.close();
+        datagramChannelSender.close();
+
+        // gets contents from datagramChannelReceiver
+        ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_AS_BYTES_LENGTH);
+        long beginTime = System.currentTimeMillis();
+        int totalRead = 0;
+        while (totalRead < CONTENT_AS_BYTES_LENGTH) {
+            totalRead += datagramChannelReceiver.read(readBuffer);
+            if (System.currentTimeMillis() - beginTime > TIME_OUT) {
+                break;
+            }
+        }
+        assertEquals(CONTENT_AS_BYTES_LENGTH, totalRead);
+
+        // compares contents.
+        readBuffer.flip();
+        for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+            assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+     */
+    public void test_transferToJJLWritableByteChannel_Pipe() throws Exception {
+        // inits data in file.
+        writeDataToFile(fileOfReadOnlyFileChannel);
+
+        // inits pipe.
+        pipe = Pipe.open();
+
+        // transfers data from fileChannel to pipe.
+        final int OFFSET = 2;
+        final int LENGTH = 4;
+        long result = readOnlyFileChannel.transferTo(OFFSET, LENGTH, pipe
+                .sink());
+        assertEquals(LENGTH, result);
+        assertEquals(0, readOnlyFileChannel.position());
+        readOnlyFileChannel.close();
+
+        // gets content from pipe.
+        ByteBuffer readBuffer = ByteBuffer.allocate(LENGTH);
+        result = pipe.source().read(readBuffer);
+        assertEquals(LENGTH, result);
+
+        // compares content.
+        readBuffer.flip();
+        for (int i = OFFSET; i < OFFSET + LENGTH; i++) {
+            assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+        }
+    }
+
+    /**
+     * Regression test for Harmony-3324
+     * Make sure we could delete the file after we called transferTo() method.
+     */
+    public void test_transferTo_couldDelete() throws Exception {
+        // init data in files
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        // call transferTo() method
+        readOnlyFileChannel.transferTo(0 , 2, writeOnlyFileChannel);
+
+        // delete both files
+        readOnlyFileChannel.close();
+        writeOnlyFileChannel.close();
+        boolean rDel = fileOfReadOnlyFileChannel.delete();
+        boolean wDel = fileOfWriteOnlyFileChannel.delete();
+
+        // make sure both files were deleted
+        assertTrue("File " + readOnlyFileChannel + " exists", rDel);
+        assertTrue("File " + writeOnlyFileChannel + " exists", wDel);
+    }
+
+    /**
+     * Regression test for Harmony-3324
+     * Make sure we could delete the file after we called transferFrom() method.
+     */
+    public void test_transferFrom_couldDelete() throws Exception {
+        // init data in files
+        writeDataToFile(fileOfReadOnlyFileChannel);
+        writeDataToFile(fileOfWriteOnlyFileChannel);
+
+        // call transferTo() method
+        writeOnlyFileChannel.transferFrom(readOnlyFileChannel, 0 , 2);
+
+        // delete both files
+        readOnlyFileChannel.close();
+        writeOnlyFileChannel.close();
+        boolean rDel = fileOfReadOnlyFileChannel.delete();
+        boolean wDel = fileOfWriteOnlyFileChannel.delete();
+
+        // make sure both files were deleted
+        assertTrue("File " + readOnlyFileChannel + " exists", rDel);
+        assertTrue("File " + writeOnlyFileChannel + " exists", wDel);
+    }
+
+    private class MockFileChannel extends FileChannel {
+
+        private boolean isLockCalled = false;
+
+        private boolean isTryLockCalled = false;
+
+        private boolean isReadCalled = false;
+
+        private boolean isWriteCalled = false;
+
+        public void force(boolean arg0) throws IOException {
+            // do nothing
+        }
+
+        public FileLock lock(long position, long size, boolean shared)
+                throws IOException {
+            // verify that calling lock() leads to the method
+            // lock(0, Long.MAX_VALUE, false).
+            if (0 == position && Long.MAX_VALUE == size && false == shared) {
+                isLockCalled = true;
+            }
+            return null;
+        }
+
+        public MappedByteBuffer map(MapMode arg0, long arg1, long arg2)
+                throws IOException {
+            return null;
+        }
+
+        public long position() throws IOException {
+            return 0;
+        }
+
+        public FileChannel position(long arg0) throws IOException {
+            return null;
+        }
+
+        public int read(ByteBuffer arg0) throws IOException {
+            return 0;
+        }
+
+        public int read(ByteBuffer arg0, long arg1) throws IOException {
+            return 0;
+        }
+
+        public long read(ByteBuffer[] srcs, int offset, int length)
+                throws IOException {
+            // verify that calling read(ByteBuffer[] srcs) leads to the method
+            // read(srcs, 0, srcs.length)
+            if (0 == offset && length == srcs.length) {
+                isReadCalled = true;
+            }
+            return 0;
+        }
+
+        public long size() throws IOException {
+            return 0;
+        }
+
+        public long transferFrom(ReadableByteChannel arg0, long arg1, long arg2)
+                throws IOException {
+            return 0;
+        }
+
+        public long transferTo(long arg0, long arg1, WritableByteChannel arg2)
+                throws IOException {
+            return 0;
+        }
+
+        public FileChannel truncate(long arg0) throws IOException {
+            return null;
+        }
+
+        public FileLock tryLock(long position, long size, boolean shared)
+                throws IOException {
+            // verify that calling tryLock() leads to the method
+            // tryLock(0, Long.MAX_VALUE, false).
+            if (0 == position && Long.MAX_VALUE == size && false == shared) {
+                isTryLockCalled = true;
+            }
+            return null;
+        }
+
+        public int write(ByteBuffer arg0) throws IOException {
+            return 0;
+        }
+
+        public int write(ByteBuffer arg0, long arg1) throws IOException {
+            return 0;
+        }
+
+        public long write(ByteBuffer[] srcs, int offset, int length)
+                throws IOException {
+            // verify that calling write(ByteBuffer[] srcs) leads to the method
+            // write(srcs, 0, srcs.length)
+            if(0 == offset && length == srcs.length){
+                isWriteCalled = true;
+            }
+            return 0;
+        }
+
+        protected void implCloseChannel() throws IOException {
+
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java
new file mode 100644
index 0000000..b60096c
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java
@@ -0,0 +1,55 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.FileLockInterruptionException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for FileLockInterruptionException
+ */
+public class FileLockInterruptionExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.FileLockInterruptionException#FileLockInterruptionException()}
+     */
+    public void test_Constructor() {
+        FileLockInterruptionException e = new FileLockInterruptionException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new FileLockInterruptionException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this,
+                new FileLockInterruptionException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java
new file mode 100644
index 0000000..12142e8
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java
@@ -0,0 +1,199 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests class FileLock.
+ */
+public class FileLockTest extends TestCase {
+
+	private FileChannel readWriteChannel;
+
+	private MockFileLock mockLock;
+
+	class MockFileLock extends FileLock {
+
+		boolean isValid = true;
+
+		protected MockFileLock(FileChannel channel, long position, long size,
+				boolean shared) {
+			super(channel, position, size, shared);
+		}
+
+		public boolean isValid() {
+			return isValid;
+		}
+
+		public void release() throws IOException {
+			isValid = false;
+		}
+	}
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		File tempFile = File.createTempFile("testing", "tmp");
+		tempFile.deleteOnExit();
+		RandomAccessFile randomAccessFile = new RandomAccessFile(tempFile, "rw");
+		readWriteChannel = randomAccessFile.getChannel();
+		mockLock = new MockFileLock(readWriteChannel, 10, 100, false);
+	}
+
+	protected void tearDown() throws IOException {
+	    if (readWriteChannel != null) {
+	        readWriteChannel.close();
+	    }
+	}
+
+	/**
+	 * @tests java.nio.channels.FileLock#FileLock(FileChannel, long, long,
+	 *        boolean)
+	 */
+	public void test_Constructor_Ljava_nio_channels_FileChannelJJZ() {
+		FileLock fileLock1 = new MockFileLock(null, 0, 0, false);
+		assertNull(fileLock1.channel());
+
+		try {
+			new MockFileLock(readWriteChannel, -1, 0, false);
+			fail("should throw IllegalArgumentException.");
+		} catch (IllegalArgumentException ex) {
+			// expected
+		}
+		try {
+			new MockFileLock(readWriteChannel, 0, -1, false);
+			fail("should throw IllegalArgumentException.");
+		} catch (IllegalArgumentException ex) {
+			// expected
+		}
+        // Harmony-682 regression test
+        try {
+            new MockFileLock(readWriteChannel, Long.MAX_VALUE, 1, false);
+            fail("should throw IllegalArgumentException.");
+        } catch (IllegalArgumentException ex) {
+            // expected
+        }
+	}
+
+	/**
+	 * @tests java.nio.channels.FileLock#channel()
+	 */
+	public void test_channel() {
+		assertSame(readWriteChannel, mockLock.channel());
+		FileLock lock = new MockFileLock(null, 0, 10, true);
+		assertNull(lock.channel());
+	}
+
+	/**
+	 * @tests java.nio.channels.FileLock#position()
+	 */
+	public void test_position() {
+		FileLock fileLock1 = new MockFileLock(readWriteChannel, 20, 100, true);
+		assertEquals(20, fileLock1.position());
+
+		final long position = ((long) Integer.MAX_VALUE + 1);
+		FileLock fileLock2 = new MockFileLock(readWriteChannel, position, 100,
+				true);
+		assertEquals(position, fileLock2.position());
+	}
+
+	/**
+	 * @tests java.nio.channels.FileLock#size()
+	 */
+	public void test_size() {
+		FileLock fileLock1 = new MockFileLock(readWriteChannel, 20, 100, true);
+		assertEquals(100, fileLock1.size());
+
+		final long position = 0x0FFFFFFFFFFFFFFFL;
+		final long size = ((long) Integer.MAX_VALUE + 1);
+		FileLock fileLock2 = new MockFileLock(readWriteChannel, position, size,
+				true);
+		assertEquals(size, fileLock2.size());
+	}
+
+	/**
+	 * @tests java.nio.channels.FileLock#isShared()
+	 */
+	public void test_isShared() {
+		assertFalse(mockLock.isShared());
+		FileLock lock = new MockFileLock(null, 0, 10, true);
+		assertTrue(lock.isShared());
+	}
+
+	/**
+	 * @tests java.nio.channels.FileLock#overlaps(long, long)
+	 */
+	public void test_overlaps_JJ() {
+		assertTrue(mockLock.overlaps(0, 11));
+		assertFalse(mockLock.overlaps(0, 10));
+		assertTrue(mockLock.overlaps(100, 110));
+		assertTrue(mockLock.overlaps(99, 110));
+		assertFalse(mockLock.overlaps(-1, 10));
+        //Harmony-671 regression test
+        assertTrue(mockLock.overlaps(1, 120));
+        assertTrue(mockLock.overlaps(20, 50));
+	}
+
+	/**
+	 * @tests java.nio.channels.FileLock#isValid()
+	 */
+	public void test_isValid() throws IOException {
+		FileLock fileLock = readWriteChannel.lock();
+		assertTrue(fileLock.isValid());
+		fileLock.release();
+		assertFalse(fileLock.isValid());
+	}
+    
+    /**
+     * @tests java.nio.channels.FileLock#release()
+     */
+    public void test_release() throws Exception {
+        File file = File.createTempFile("test", "tmp");
+        file.deleteOnExit();
+        FileOutputStream fout = new FileOutputStream(file);
+        FileChannel fileChannel = fout.getChannel();
+        FileLock fileLock = fileChannel.lock();
+        fileChannel.close();
+        try {
+            fileLock.release();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+        // release after release
+        fout = new FileOutputStream(file);
+        fileChannel = fout.getChannel();
+        fileLock = fileChannel.lock();
+        fileLock.release();
+        fileChannel.close();
+        try {
+            fileLock.release();
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            //expected
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java
new file mode 100644
index 0000000..a8cdf83
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java
@@ -0,0 +1,55 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.IllegalBlockingModeException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for IllegalBlockingModeException
+ */
+public class IllegalBlockingModeExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.IllegalBlockingModeException#IllegalBlockingModeException()}
+     */
+    public void test_Constructor() {
+        IllegalBlockingModeException e = new IllegalBlockingModeException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new IllegalBlockingModeException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest
+                .verifyGolden(this, new IllegalBlockingModeException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java
new file mode 100644
index 0000000..2fa3171
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.IllegalSelectorException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for IllegalSelectorException
+ */
+public class IllegalSelectorExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.IllegalSelectorException#IllegalSelectorException()}
+     */
+    public void test_Constructor() {
+        IllegalSelectorException e = new IllegalSelectorException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new IllegalSelectorException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new IllegalSelectorException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MapModeTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MapModeTest.java
new file mode 100644
index 0000000..33234eb
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MapModeTest.java
@@ -0,0 +1,52 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.FileChannel;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for FileChannel.MapMode
+ */
+public class MapModeTest extends TestCase {
+
+    /**
+     * java.nio.channels.FileChannel.MapMode#PRIVATE,READONLY,READWRITE
+     */
+    public void test_PRIVATE_READONLY_READWRITE() {
+        assertNotNull(FileChannel.MapMode.PRIVATE);
+        assertNotNull(FileChannel.MapMode.READ_ONLY);
+        assertNotNull(FileChannel.MapMode.READ_WRITE);
+
+        assertFalse(FileChannel.MapMode.PRIVATE
+                .equals(FileChannel.MapMode.READ_ONLY));
+        assertFalse(FileChannel.MapMode.PRIVATE
+                .equals(FileChannel.MapMode.READ_WRITE));
+        assertFalse(FileChannel.MapMode.READ_ONLY
+                .equals(FileChannel.MapMode.READ_WRITE));
+    }
+
+    /**
+     * java.nio.channels.FileChannel.MapMode#toString()
+     */
+    public void test_toString() {
+        assertNotNull(FileChannel.MapMode.PRIVATE.toString());
+        assertNotNull(FileChannel.MapMode.READ_ONLY.toString());
+        assertNotNull(FileChannel.MapMode.READ_WRITE.toString());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockDatagramChannel.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockDatagramChannel.java
new file mode 100644
index 0000000..c8dc2af
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockDatagramChannel.java
@@ -0,0 +1,81 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+class MockDatagramChannel extends DatagramChannel {
+
+    public MockDatagramChannel(SelectorProvider arg0) {
+        super(arg0);
+    }
+
+    public DatagramSocket socket() {
+        return null;
+    }
+
+    public boolean isConnected() {
+        return false;
+    }
+
+    public DatagramChannel connect(SocketAddress arg0) throws IOException {
+        return null;
+    }
+
+    public DatagramChannel disconnect() throws IOException {
+        return null;
+    }
+
+    public SocketAddress receive(ByteBuffer arg0) throws IOException {
+        return null;
+    }
+
+    public int send(ByteBuffer arg0, SocketAddress arg1) throws IOException {
+        return 0;
+    }
+
+    public int read(ByteBuffer arg0) throws IOException {
+        return 0;
+    }
+
+    public long read(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+        return 0;
+    }
+
+    public int write(ByteBuffer arg0) throws IOException {
+        return 0;
+    }
+
+    public long write(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+        return 0;
+    }
+
+    protected void implCloseSelectableChannel() throws IOException {
+        // empty
+    }
+
+    protected void implConfigureBlocking(boolean arg0) throws IOException {
+        // empty
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockServerSocketChannel.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockServerSocketChannel.java
new file mode 100644
index 0000000..2058a7a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockServerSocketChannel.java
@@ -0,0 +1,46 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+class MockServerSocketChannel extends ServerSocketChannel {
+
+    protected MockServerSocketChannel(SelectorProvider arg0) {
+        super(arg0);
+    }
+
+    public ServerSocket socket() {
+        return null;
+    }
+
+    public SocketChannel accept() throws IOException {
+        return null;
+    }
+
+    protected void implCloseSelectableChannel() throws IOException {
+    }
+
+    protected void implConfigureBlocking(boolean arg0) throws IOException {
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockSocketChannel.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockSocketChannel.java
new file mode 100644
index 0000000..9d130ca
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockSocketChannel.java
@@ -0,0 +1,75 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+class MockSocketChannel extends SocketChannel {
+
+    protected MockSocketChannel(SelectorProvider arg0) {
+        super(arg0);
+    }
+
+    public Socket socket() {
+        return null;
+    }
+
+    public boolean isConnected() {
+        return false;
+    }
+
+    public boolean isConnectionPending() {
+        return false;
+    }
+
+    public boolean connect(SocketAddress arg0) throws IOException {
+        return false;
+    }
+
+    public boolean finishConnect() throws IOException {
+        return false;
+    }
+
+    public int read(ByteBuffer arg0) throws IOException {
+        return 0;
+    }
+
+    public long read(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+        return 0;
+    }
+
+    public int write(ByteBuffer arg0) throws IOException {
+        return 0;
+    }
+
+    public long write(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+        return 0;
+    }
+
+    protected void implCloseSelectableChannel() throws IOException {
+    }
+
+    protected void implConfigureBlocking(boolean arg0) throws IOException {
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java
new file mode 100644
index 0000000..2ba7ba6
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java
@@ -0,0 +1,55 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.NoConnectionPendingException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NoConnectionPendingException
+ */
+public class NoConnectionPendingExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.NoConnectionPendingException#NoConnectionPendingException()}
+     */
+    public void test_Constructor() {
+        NoConnectionPendingException e = new NoConnectionPendingException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new NoConnectionPendingException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest
+                .verifyGolden(this, new NoConnectionPendingException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java
new file mode 100644
index 0000000..8c44f17
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.NonReadableChannelException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NonReadableChannelException
+ */
+public class NonReadableChannelExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.NonReadableChannelException#NonReadableChannelException()}
+     */
+    public void test_Constructor() {
+        NonReadableChannelException e = new NonReadableChannelException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new NonReadableChannelException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new NonReadableChannelException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java
new file mode 100644
index 0000000..459d85a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.NonWritableChannelException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NonWritableChannelException
+ */
+public class NonWritableChannelExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.NonWritableChannelException#NonWritableChannelException()}
+     */
+    public void test_Constructor() {
+        NonWritableChannelException e = new NonWritableChannelException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new NonWritableChannelException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new NonWritableChannelException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java
new file mode 100644
index 0000000..d1c2d86
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.NotYetBoundException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NotYetBoundException
+ */
+public class NotYetBoundExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.NotYetBoundException#NotYetBoundException()}
+     */
+    public void test_Constructor() {
+        NotYetBoundException e = new NotYetBoundException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new NotYetBoundException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new NotYetBoundException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java
new file mode 100644
index 0000000..09e4c1c
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.NotYetConnectedException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NotYetConnectedException
+ */
+public class NotYetConnectedExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.NotYetConnectedException#NotYetConnectedException()}
+     */
+    public void test_Constructor() {
+        NotYetConnectedException e = new NotYetConnectedException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new NotYetConnectedException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new NotYetConnectedException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java
new file mode 100644
index 0000000..d06f807
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java
@@ -0,0 +1,55 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.OverlappingFileLockException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for OverlappingFileLockException
+ */
+public class OverlappingFileLockExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.OverlappingFileLockException#OverlappingFileLockException()}
+     */
+    public void test_Constructor() {
+        OverlappingFileLockException e = new OverlappingFileLockException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new OverlappingFileLockException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest
+                .verifyGolden(this, new OverlappingFileLockException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/PipeTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/PipeTest.java
new file mode 100644
index 0000000..53f19c4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/PipeTest.java
@@ -0,0 +1,59 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.NetPermission;
+import java.nio.channels.Pipe;
+import java.nio.channels.Pipe.SinkChannel;
+import java.nio.channels.Pipe.SourceChannel;
+import java.security.Permission;
+
+import junit.framework.TestCase;
+
+/*
+ * Tests for Pipe and its default implementation
+ */
+public class PipeTest extends TestCase {
+
+	/**
+	 * @tests java.nio.channels.Pipe#open()
+	 */
+	public void test_open() throws IOException{
+		Pipe pipe = Pipe.open();
+		assertNotNull(pipe);
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe#sink()
+	 */
+	public void test_sink() throws IOException {
+		Pipe pipe = Pipe.open();
+		SinkChannel sink = pipe.sink();
+		assertTrue(sink.isBlocking());
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe#source()
+	 */
+	public void test_source() throws IOException {
+		Pipe pipe = Pipe.open();
+		SourceChannel source = pipe.source();
+		assertTrue(source.isBlocking());
+	}
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectableChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectableChannelTest.java
new file mode 100644
index 0000000..25b5f00
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectableChannelTest.java
@@ -0,0 +1,89 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.SelectorProvider;
+import junit.framework.TestCase;
+
+/*
+ * Tests for SelectableChannel
+ */
+public class SelectableChannelTest extends TestCase {
+
+    /**
+     * @tests SelectableChannel#register(Selector, int)
+     */
+    public void test_register_LSelectorI() throws IOException {
+        MockSelectableChannel msc = new MockSelectableChannel();
+        // Verify that calling register(Selector, int) leads to the method
+        // register(Selector, int, Object) being called with a null value 
+        // for the third argument.
+        msc.register(Selector.open(), SelectionKey.OP_ACCEPT);
+        assertTrue(msc.isCalled);
+    }
+
+    private class MockSelectableChannel extends SelectableChannel {
+
+        private boolean isCalled = false;
+
+        public Object blockingLock() {
+            return null;
+        }
+
+        public SelectableChannel configureBlocking(boolean block)
+                throws IOException {
+            return null;
+        }
+
+        public boolean isBlocking() {
+            return false;
+        }
+
+        public boolean isRegistered() {
+            return false;
+        }
+
+        public SelectionKey keyFor(Selector sel) {
+            return null;
+        }
+
+        public SelectorProvider provider() {
+            return null;
+        }
+
+        public SelectionKey register(Selector sel, int ops, Object att)
+                throws ClosedChannelException {
+            if (null == att) {
+                isCalled = true;
+            }
+            return null;
+        }
+
+        public int validOps() {
+            return 0;
+        }
+
+        protected void implCloseChannel() throws IOException {
+            // empty
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectionKeyTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectionKeyTest.java
new file mode 100644
index 0000000..ed33752
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectionKeyTest.java
@@ -0,0 +1,321 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/*
+ * Tests for SelectionKey and its default implementation
+ */
+public class SelectionKeyTest extends TestCase {
+
+    Selector selector;
+
+    SocketChannel sc;
+
+    SelectionKey selectionKey;
+
+    private static String LOCAL_ADDR = "127.0.0.1";
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        selector = Selector.open();
+        sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        selectionKey = sc.register(selector, SelectionKey.OP_CONNECT);
+    }
+
+    protected void tearDown() throws Exception {
+        selectionKey.cancel();
+        selectionKey = null;
+        selector.close();
+        selector = null;
+        super.tearDown();
+    }
+
+    static class MockSelectionKey extends SelectionKey {
+        private int interestOps;
+
+        MockSelectionKey(int ops) {
+            interestOps = ops;
+        }
+
+        public void cancel() {
+            // do nothing
+        }
+
+        public SelectableChannel channel() {
+            return null;
+        }
+
+        public int interestOps() {
+            return 0;
+        }
+
+        public SelectionKey interestOps(int operations) {
+            return null;
+        }
+
+        public boolean isValid() {
+            return true;
+        }
+
+        public int readyOps() {
+            return interestOps;
+        }
+
+        public Selector selector() {
+            return null;
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#attach(Object)
+     */
+    public void test_attach() {
+        MockSelectionKey mockSelectionKey = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+        // no previous, return null
+        Object o = new Object();
+        Object check = mockSelectionKey.attach(o);
+        assertNull(check);
+
+        // null parameter is ok
+        check = mockSelectionKey.attach(null);
+        assertSame(o, check);
+
+        check = mockSelectionKey.attach(o);
+        assertNull(check);
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#attachment()
+     */
+    public void test_attachment() {
+        MockSelectionKey mockSelectionKey = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+        assertNull(mockSelectionKey.attachment());
+        Object o = new Object();
+        mockSelectionKey.attach(o);
+        assertSame(o, mockSelectionKey.attachment());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#channel()
+     */
+    public void test_channel() {
+        assertSame(sc, selectionKey.channel());
+        // can be invoked even canceled
+        selectionKey.cancel();
+        assertSame(sc, selectionKey.channel());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#interestOps()
+     */
+    public void test_interestOps() {
+        assertEquals(SelectionKey.OP_CONNECT, selectionKey.interestOps());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#interestOps(int)
+     */
+    public void test_interestOpsI() {
+        selectionKey.interestOps(SelectionKey.OP_WRITE);
+        assertEquals(SelectionKey.OP_WRITE, selectionKey.interestOps());
+
+        try {
+            selectionKey.interestOps(SelectionKey.OP_ACCEPT);
+            fail("should throw IAE.");
+        } catch (IllegalArgumentException ex) {
+            // expected;
+        }
+
+        try {
+            selectionKey.interestOps(~sc.validOps());
+            fail("should throw IAE.");
+        } catch (IllegalArgumentException ex) {
+            // expected;
+        }
+        try {
+            selectionKey.interestOps(-1);
+            fail("should throw IAE.");
+        } catch (IllegalArgumentException ex) {
+            // expected;
+        }
+        
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#isValid()
+     */
+    public void test_isValid() {
+        assertTrue(selectionKey.isValid());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#isValid()
+     */
+    public void test_isValid_KeyCancelled() {
+        selectionKey.cancel();
+        assertFalse(selectionKey.isValid());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#isValid()
+     */
+    public void test_isValid_ChannelColsed() throws IOException {
+        sc.close();
+        assertFalse(selectionKey.isValid());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#isValid()
+     */
+    public void test_isValid_SelectorClosed() throws IOException {
+        selector.close();
+        assertFalse(selectionKey.isValid());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#isAcceptable()
+     */
+    public void test_isAcceptable() throws IOException {
+        MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+        assertTrue(mockSelectionKey1.isAcceptable());
+        MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_CONNECT);
+        assertFalse(mockSelectionKey2.isAcceptable());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#isConnectable()
+     */
+    public void test_isConnectable() {
+        MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_CONNECT);
+        assertTrue(mockSelectionKey1.isConnectable());
+        MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+        assertFalse(mockSelectionKey2.isConnectable());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#isReadable()
+     */
+    public void test_isReadable() {
+        MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_READ);
+        assertTrue(mockSelectionKey1.isReadable());
+        MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+        assertFalse(mockSelectionKey2.isReadable());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#isWritable()
+     */
+    public void test_isWritable() {
+        MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_WRITE);
+        assertTrue(mockSelectionKey1.isWritable());
+        MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+        assertFalse(mockSelectionKey2.isWritable());
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#cancel()
+     */
+    public void test_cancel() {
+        selectionKey.cancel();
+        try {
+            selectionKey.isAcceptable();
+            fail("should throw CancelledKeyException.");
+        } catch (CancelledKeyException ex) {
+            // expected
+        }
+        try {
+            selectionKey.isConnectable();
+            fail("should throw CancelledKeyException.");
+        } catch (CancelledKeyException ex) {
+            // expected
+        }
+        try {
+            selectionKey.isReadable();
+            fail("should throw CancelledKeyException.");
+        } catch (CancelledKeyException ex) {
+            // expected
+        }
+        try {
+            selectionKey.isWritable();
+            fail("should throw CancelledKeyException.");
+        } catch (CancelledKeyException ex) {
+            // expected
+        }
+        
+        try {
+            selectionKey.readyOps();
+            fail("should throw CancelledKeyException.");
+        } catch (CancelledKeyException ex) {
+            // expected
+        }
+        
+        try {
+            selectionKey.interestOps(SelectionKey.OP_CONNECT);
+            fail("should throw CancelledKeyException.");
+        } catch (CancelledKeyException ex) {
+            // expected
+        }
+        
+        try {
+            selectionKey.interestOps();
+            fail("should throw CancelledKeyException.");
+        } catch (CancelledKeyException ex) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#readyOps()
+     */
+    public void test_readyOps() throws IOException {
+        int port = Support_PortManager.getNextPort();
+        ServerSocket ss = new ServerSocket(port);
+        try {
+            sc.connect(new InetSocketAddress(LOCAL_ADDR, port));
+            assertEquals(0, selectionKey.readyOps());
+            assertFalse(selectionKey.isConnectable());
+            selector.select();
+            assertEquals(SelectionKey.OP_CONNECT, selectionKey.readyOps());
+        } finally {
+            ss.close();
+            ss = null;
+        }
+      
+    }
+
+    /**
+     * @tests java.nio.channels.SelectionKey#selector()
+     */
+    public void test_selector() {
+        assertSame(selector, selectionKey.selector());
+        selectionKey.cancel();
+        assertSame(selector, selectionKey.selector());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java
new file mode 100644
index 0000000..3617230
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java
@@ -0,0 +1,685 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.Set;
+import junit.framework.TestCase;
+
+/*
+ * Tests for Selector and its default implementation
+ */
+public class SelectorTest extends TestCase {
+    private static final int WAIT_TIME = 100;
+
+    private SocketAddress localAddress;
+
+    private Selector selector;
+
+    private ServerSocketChannel ssc;
+
+    private enum SelectType {
+        NULL, TIMEOUT, NOW
+    };
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        ssc = ServerSocketChannel.open();
+        ssc.configureBlocking(false);
+        ServerSocket ss = ssc.socket();
+        ss.bind(null);
+        localAddress = ss.getLocalSocketAddress();
+        selector = Selector.open();
+    }
+
+    protected void tearDown() throws Exception {
+        try {
+            ssc.close();
+        } catch (Exception e) {
+            // do nothing
+        }
+        try {
+            selector.close();
+        } catch (Exception e) {
+            // do nothing
+        }
+        super.tearDown();
+    }
+
+    /**
+     * @tests java.nio.channels.Selector#open()
+     */
+    public void test_open() throws IOException {
+        assertNotNull(selector);
+    }
+
+    /**
+     * @tests Selector#isOpen()
+     */
+    public void test_isOpen() throws IOException {
+        assertTrue(selector.isOpen());
+        selector.close();
+        assertFalse(selector.isOpen());
+    }
+
+    /**
+     * @tests java.nio.channels.Selector#provider()
+     */
+    public void test_provider() throws IOException {
+        // should be system default provider
+        assertNotNull(selector.provider());
+        assertSame(SelectorProvider.provider(), selector.provider());
+    }
+
+    /**
+     * @tests java.nio.channels.Selector#keys()
+     */
+    public void test_keys() throws IOException {
+        SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);
+
+        Set<SelectionKey> keySet = selector.keys();
+        Set<SelectionKey> keySet2 = selector.keys();
+
+        assertSame(keySet, keySet2);
+        assertEquals(1,keySet.size());
+        SelectionKey key2 = keySet.iterator().next();
+        assertEquals(key,key2);
+
+        // Any attempt to modify keys will cause UnsupportedOperationException
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        SelectionKey key3 = sc.register(selector, SelectionKey.OP_READ);
+        try {
+            keySet2.add(key3);
+            fail("should throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+            // expected
+        }
+        try {
+            keySet2.remove(key3);
+            fail("should throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+            // expected
+        }
+        try {
+            keySet2.clear();
+            fail("should throw UnsupportedOperationException");
+        } catch (UnsupportedOperationException e) {
+            // expected
+        }
+
+        selector.close();
+        try {
+            selector.keys();
+            fail("should throw ClosedSelectorException");
+        } catch (ClosedSelectorException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.Selector#keys()
+     */
+    public void test_selectedKeys() throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        ssc.register(selector, SelectionKey.OP_ACCEPT);
+        try {
+            int count = 0;
+            sc.connect(localAddress);
+            count = blockingSelect(SelectType.NULL, 0);
+            assertEquals(1, count);
+            Set<SelectionKey> selectedKeys = selector.selectedKeys();
+            Set<SelectionKey> selectedKeys2 = selector.selectedKeys();
+            assertSame(selectedKeys, selectedKeys2);
+
+            assertEquals(1, selectedKeys.size());
+            assertEquals(ssc.keyFor(selector), selectedKeys.iterator().next());
+            // add one key into selectedKeys
+            try {
+                selectedKeys.add(ssc.keyFor(selector));
+                fail("Should throw UnsupportedOperationException");
+            } catch (UnsupportedOperationException e) {
+                // expected
+            }
+
+            // no exception should be thrown
+            selectedKeys.clear();
+
+            Set<SelectionKey> selectedKeys3 = selector.selectedKeys();
+            assertSame(selectedKeys, selectedKeys3);
+
+            ssc.keyFor(selector).cancel();
+            assertEquals(0, selectedKeys.size());
+            selector.close();
+            try {
+                selector.selectedKeys();
+                fail("should throw ClosedSelectorException");
+            } catch (ClosedSelectorException e) {
+                // expected
+            }
+        } finally {
+            sc.close();
+        }
+    }
+
+    /**
+     * @tests java.nio.channel.Selector#selectNow()
+     */
+    public void test_selectNow() throws IOException {
+        assert_select_OP_ACCEPT(SelectType.NOW, 0);
+        assert_select_OP_CONNECT(SelectType.NOW, 0);
+        assert_select_OP_READ(SelectType.NOW, 0);
+        assert_select_OP_WRITE(SelectType.NOW, 0);
+    }
+
+    /**
+     * @tests java.nio.channel.Selector#selectNow()
+     */
+    public void test_selectNow_SelectorClosed() throws IOException {
+        assert_select_SelectorClosed(SelectType.NOW, 0);
+    }
+
+    /**
+     * @test java.nio.channels.Selector#selectNow()
+     */
+    public void test_selectNow_Timeout() throws IOException {
+        // make sure selectNow doesn't block
+        selector.selectNow();
+    }
+
+    /**
+     * @tests java.nio.channel.Selector#select()
+     */
+    public void test_select() throws IOException {
+        assert_select_OP_ACCEPT(SelectType.NULL, 0);
+        assert_select_OP_CONNECT(SelectType.NULL, 0);
+        assert_select_OP_READ(SelectType.NULL, 0);
+        assert_select_OP_WRITE(SelectType.NULL, 0);
+    }
+
+    /**
+     * @tests java.nio.channel.Selector#select()
+     */
+    public void test_select_SelectorClosed() throws IOException {
+        assert_select_SelectorClosed(SelectType.NULL, 0);
+    }
+
+    /**
+     * @tests java.nio.channel.Selector#select(long)
+     */
+    public void test_selectJ() throws IOException {
+        assert_select_OP_ACCEPT(SelectType.TIMEOUT, 0);
+        assert_select_OP_CONNECT(SelectType.TIMEOUT, 0);
+        assert_select_OP_READ(SelectType.TIMEOUT, 0);
+        assert_select_OP_WRITE(SelectType.TIMEOUT, 0);
+
+        assert_select_OP_ACCEPT(SelectType.TIMEOUT, WAIT_TIME);
+        assert_select_OP_CONNECT(SelectType.TIMEOUT, WAIT_TIME);
+        assert_select_OP_READ(SelectType.TIMEOUT, WAIT_TIME);
+        assert_select_OP_WRITE(SelectType.TIMEOUT, WAIT_TIME);
+    }
+
+    /**
+     * @tests java.nio.channel.Selector#select(long)
+     */
+    public void test_selectJ_SelectorClosed() throws IOException {
+        assert_select_SelectorClosed(SelectType.TIMEOUT, 0);
+        selector = Selector.open();
+        assert_select_SelectorClosed(SelectType.TIMEOUT, WAIT_TIME);
+    }
+
+    /**
+     * @tests java.nio.channel.Selector#select(long)
+     */
+    public void test_selectJ_Exception() throws IOException {
+        try {
+            selector.select(-1);
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @test java.nio.channels.Selector#select(long)
+     */
+    public void test_selectJ_Timeout() throws IOException {
+        // make sure select(timeout) doesn't block
+        selector.select(WAIT_TIME);
+    }
+
+    /**
+     * @test java.nio.channels.Selector#select(long)
+     */
+    public void test_selectJ_Empty_Keys() throws IOException {
+        // regression test, see HARMONY-3888.
+        // make sure select(long) does wait for specified amount of
+        // time if keys.size() == 0 (initial state of selector).
+
+        final long SELECT_TIMEOUT_MS = 2000;
+
+        long t0 = System.nanoTime();
+        selector.select(SELECT_TIMEOUT_MS);
+        long t1 = System.nanoTime();
+
+        long waitMs = (t1 - t0) / 1000L / 1000L;
+        assertTrue(waitMs >= SELECT_TIMEOUT_MS);
+        assertTrue(waitMs < 5*SELECT_TIMEOUT_MS);
+    }
+
+    /**
+     * @tests java.nio.channels.Selector#wakeup()
+     */
+    public void test_wakeup() throws IOException {
+        /*
+         * make sure the test does not block on select
+         */
+        selector.wakeup();
+        selectOnce(SelectType.NULL, 0);
+        selector.wakeup();
+        selectOnce(SelectType.TIMEOUT, 0);
+
+        // try to wakeup select. The invocation sequence of wakeup and select
+        // doesn't affect test result.
+        new Thread() {
+            public void run() {
+
+                try {
+                    Thread.sleep(WAIT_TIME);
+                } catch (InterruptedException e) {
+                    // ignore
+                }
+                selector.wakeup();
+            }
+        }.start();
+        selectOnce(SelectType.NULL, 0);
+
+        // try to wakeup select. The invocation sequence of wakeup and select
+        // doesn't affect test result.
+        new Thread() {
+            public void run() {
+
+                try {
+                    Thread.sleep(WAIT_TIME);
+                } catch (InterruptedException e) {
+                    // ignore
+                }
+                selector.wakeup();
+            }
+        }.start();
+        selectOnce(SelectType.TIMEOUT, 0);
+    }
+
+    public void test_keySetViewsModifications() throws IOException {
+        Set<SelectionKey> keys = selector.keys();
+
+        SelectionKey key1 = ssc.register(selector, SelectionKey.OP_ACCEPT);
+
+        assertTrue(keys.contains(key1));
+
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        SelectionKey key2 = sc.register(selector, SelectionKey.OP_READ);
+
+        assertTrue(keys.contains(key1));
+        assertTrue(keys.contains(key2));
+
+        key1.cancel();
+        assertTrue(keys.contains(key1));
+
+        selector.selectNow();
+        assertFalse(keys.contains(key1));
+        assertTrue(keys.contains(key2));
+     }
+
+    /**
+     * This test cancels a key while selecting to verify that the cancelled
+     * key set is processed both before and after the call to the underlying
+     * operating system.
+     */
+    public void test_cancelledKeys() throws Exception {
+        final AtomicReference<Throwable> failure = new AtomicReference<Throwable>();
+        final AtomicBoolean complete = new AtomicBoolean();
+
+        final Pipe pipe = Pipe.open();
+        pipe.source().configureBlocking(false);
+        final SelectionKey key = pipe.source().register(selector, SelectionKey.OP_READ);
+
+        Thread thread = new Thread() {
+            public void run() {
+                try {
+                    // make sure to call key.cancel() while the main thread is selecting
+                    Thread.sleep(500);
+                    key.cancel();
+                    assertFalse(key.isValid());
+                    pipe.sink().write(ByteBuffer.allocate(4)); // unblock select()
+                } catch (Throwable e) {
+                    failure.set(e);
+                } finally {
+                    complete.set(true);
+                }
+            }
+        };
+        assertTrue(key.isValid());
+
+        thread.start();
+        do {
+            assertEquals(0, selector.select(5000)); // blocks
+            assertEquals(0, selector.selectedKeys().size());
+        } while (!complete.get()); // avoid spurious interrupts
+        assertFalse(key.isValid());
+
+        thread.join();
+        assertNull(failure.get());
+    }
+
+    public void testOpChange() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        sc.register(selector, SelectionKey.OP_CONNECT);
+        try {
+            sc.connect(localAddress);
+            int count = blockingSelect(SelectType.TIMEOUT, 100);
+            assertEquals(1, count);
+            Set<SelectionKey> selectedKeys = selector.selectedKeys();
+            assertEquals(1, selectedKeys.size());
+            SelectionKey key = selectedKeys.iterator().next();
+            assertEquals(sc.keyFor(selector), key);
+            assertEquals(SelectionKey.OP_CONNECT, key.readyOps());
+            // select again, it should return 0
+            count = selectOnce(SelectType.TIMEOUT, 100);
+            assertEquals(0, count);
+            // but selectedKeys remains the same as previous
+            assertSame(selectedKeys, selector.selectedKeys());
+            sc.finishConnect();
+
+            // same selector, but op is changed
+            SelectionKey key1 = sc.register(selector, SelectionKey.OP_WRITE);
+            assertEquals(key, key1);
+            count = blockingSelect(SelectType.TIMEOUT, 100);
+            assertEquals(1, count);
+            selectedKeys = selector.selectedKeys();
+            assertEquals(1, selectedKeys.size());
+            key = selectedKeys.iterator().next();
+            assertEquals(key, key1);
+            assertEquals(SelectionKey.OP_WRITE, key.readyOps());
+
+            selectedKeys.clear();
+        } finally {
+            try {
+                ssc.accept().close();
+            } catch (Exception e) {
+                // do nothing
+            }
+            try {
+                sc.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+    }
+
+    public void test_nonBlockingConnect() throws IOException {
+        SocketChannel channel = null;
+        try {
+            channel = SocketChannel.open();
+            channel.configureBlocking(false);
+            Selector selector = Selector.open();
+            channel.register(selector, SelectionKey.OP_CONNECT);
+            channel.connect(localAddress);
+            channel.finishConnect();
+            selector.select();
+            assertEquals(0, selector.selectedKeys().size());
+        } finally {
+            channel.close();
+        }
+    }
+
+    private void assert_select_SelectorClosed(SelectType type, int timeout)
+            throws IOException {
+        // selector is closed
+        selector.close();
+        try {
+            selectOnce(type, timeout);
+            fail("should throw ClosedSelectorException");
+        } catch (ClosedSelectorException e) {
+            // expected
+        }
+    }
+
+    private void assert_select_OP_ACCEPT(SelectType type, int timeout)
+            throws IOException, ClosedChannelException {
+        SocketChannel sc = SocketChannel.open();
+        SocketChannel client = null;
+        try {
+            ssc.register(selector, SelectionKey.OP_ACCEPT);
+            sc.connect(localAddress);
+            int count = blockingSelect(type, timeout);
+            assertEquals(1, count);
+            Set<SelectionKey> selectedKeys = selector.selectedKeys();
+            assertEquals(1, selectedKeys.size());
+            SelectionKey key = selectedKeys.iterator().next();
+            assertEquals(ssc.keyFor(selector), key);
+            assertEquals(SelectionKey.OP_ACCEPT, key.readyOps());
+            // select again, it should return 0
+            count = selectOnce(type, timeout);
+            assertEquals(0,count);
+            // but selectedKeys remains the same as previous
+            assertSame(selectedKeys, selector.selectedKeys());
+            client = ssc.accept();
+            selectedKeys.clear();
+        } finally {
+            try {
+                sc.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+            if (null != client) {
+                client.close();
+            }
+        }
+        ssc.keyFor(selector).cancel();
+    }
+
+    private void assert_select_OP_CONNECT(SelectType type, int timeout)
+            throws IOException, ClosedChannelException {
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        sc.register(selector, SelectionKey.OP_CONNECT);
+        try {
+            sc.connect(localAddress);
+            int count = blockingSelect(type, timeout);
+            assertEquals(1, count);
+            Set<SelectionKey> selectedKeys = selector.selectedKeys();
+            assertEquals(1, selectedKeys.size());
+            SelectionKey key = selectedKeys.iterator().next();
+            assertEquals(sc.keyFor(selector), key);
+            assertEquals(SelectionKey.OP_CONNECT, key.readyOps());
+            // select again, it should return 0
+            count = selectOnce(type, timeout);
+            assertEquals(0, count);
+            // but selectedKeys remains the same as previous
+            assertSame(selectedKeys, selector.selectedKeys());
+            sc.finishConnect();
+            selectedKeys.clear();
+        } finally {
+            try {
+                ssc.accept().close();
+            } catch (Exception e) {
+                // do nothing
+            }
+
+            try {
+                sc.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+        }
+    }
+
+    private void assert_select_OP_READ(SelectType type, int timeout)
+            throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        SocketChannel client = null;
+        SocketChannel sc2 = SocketChannel.open();
+        SocketChannel client2 = null;
+        try {
+            ssc.configureBlocking(true);
+            sc.connect(localAddress);
+            client = ssc.accept();
+            sc.configureBlocking(false);
+            sc.register(selector, SelectionKey.OP_READ);
+            client.configureBlocking(true);
+
+            sc2.connect(localAddress);
+            client2 = ssc.accept();
+            sc2.configureBlocking(false);
+            sc2.register(selector, SelectionKey.OP_READ);
+            client2.configureBlocking(true);
+
+            client.write(ByteBuffer.wrap("a".getBytes()));
+            int count = blockingSelect(type, timeout);
+            assertEquals(1, count);
+            Set<SelectionKey> selectedKeys = selector.selectedKeys();
+            assertEquals(1, selectedKeys.size());
+            SelectionKey key = selectedKeys.iterator().next();
+            assertEquals(sc.keyFor(selector), key);
+            assertEquals(SelectionKey.OP_READ, key.readyOps());
+            // select again, it should return 0
+            count = selectOnce(type, timeout);
+            assertEquals(0, count);
+            // but selectedKeys remains the same as previous
+            assertSame(selectedKeys, selector.selectedKeys());
+
+            sc.read(ByteBuffer.allocate(8));
+
+            // the second SocketChannel should be selected this time
+            client2.write(ByteBuffer.wrap("a".getBytes()));
+            count = blockingSelect(type, timeout);
+            assertEquals(1, count);
+            // selectedKeys still includes the key of sc, because the key of sc
+            // is not removed last time.
+            selectedKeys = selector.selectedKeys();
+            assertEquals(2, selectedKeys.size());
+        } finally {
+            if (null != client) {
+                try {
+                    client.close();
+                } catch (Exception e) {
+                    // ignore
+                }
+            }
+            if (null != client2) {
+                try {
+                    client2.close();
+                } catch (Exception e) {
+                    // ignore
+                }
+            }
+            try {
+                sc.close();
+            } catch (Exception e) {
+                // ignore
+            }
+            try {
+                sc2.close();
+            } catch (Exception e) {
+                // ignore
+            }
+            ssc.configureBlocking(false);
+        }
+    }
+
+    private void assert_select_OP_WRITE(SelectType type, int timeout)
+            throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        SocketChannel client = null;
+        try {
+            sc.connect(localAddress);
+            ssc.configureBlocking(true);
+            client = ssc.accept();
+            sc.configureBlocking(false);
+            sc.register(selector, SelectionKey.OP_WRITE);
+            int count = blockingSelect(type, timeout);
+            assertEquals(1, count);
+            Set<SelectionKey> selectedKeys = selector.selectedKeys();
+            assertEquals(1, selectedKeys.size());
+            SelectionKey key = selectedKeys.iterator().next();
+            assertEquals(sc.keyFor(selector), key);
+            assertEquals(SelectionKey.OP_WRITE, key.readyOps());
+            // select again, it should return 0
+            count = selectOnce(type, timeout);
+            assertEquals(0, count);
+            // but selectedKeys remains the same as previous
+            assertSame(selectedKeys, selector.selectedKeys());
+        } finally {
+            if (null != client) {
+                client.close();
+            }
+            try {
+                sc.close();
+            } catch (IOException e) {
+                // do nothing
+            }
+            ssc.configureBlocking(false);
+        }
+    }
+
+    private int blockingSelect(SelectType type, int timeout) throws IOException {
+        int ret = 0;
+        do {
+            ret = selectOnce(type, timeout);
+            if (ret > 0) {
+                return ret;
+            }
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+                // ignore
+            }
+        } while (true);
+    }
+
+    private int selectOnce(SelectType type, int timeout) throws IOException {
+        int ret = 0;
+        switch (type) {
+        case NULL:
+            ret = selector.select();
+            break;
+        case TIMEOUT:
+            ret = selector.select(timeout);
+            break;
+        case NOW:
+            ret = selector.selectNow();
+            break;
+        }
+        return ret;
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ServerSocketChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ServerSocketChannelTest.java
new file mode 100644
index 0000000..fdbbc48
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ServerSocketChannelTest.java
@@ -0,0 +1,682 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/*
+ * test for ServerSocketChannel
+ */
+public class ServerSocketChannelTest extends TestCase {
+
+    private static final int CAPACITY_NORMAL = 200;
+
+    private static final int CAPACITY_64KB = 65536;
+
+    private static final int TIME_UNIT = 200;
+
+    private InetSocketAddress localAddr1;
+
+    private ServerSocketChannel serverChannel;
+
+    private SocketChannel clientChannel;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.localAddr1 = new InetSocketAddress(
+                "127.0.0.1", Support_PortManager
+                        .getNextPort());
+        this.serverChannel = ServerSocketChannel.open();
+        this.clientChannel = SocketChannel.open();
+    }
+
+    protected void tearDown() throws Exception {
+        if (null != this.serverChannel) {
+            try {
+                this.serverChannel.close();
+            } catch (Exception e) {
+                //ignore
+            }
+
+        }
+        if (null != this.clientChannel) {
+            try {
+                this.clientChannel.close();
+            } catch (Exception e) {
+                //ignore
+            }
+        }
+        super.tearDown();
+    }
+
+    // -------------------------------------------------------------------
+    // Test for methods in abstract class.
+    // -------------------------------------------------------------------
+
+    /*
+     * Test method for 'java.nio.channels.ServerSocketChannel.validOps()'
+     */
+    public void testValidOps() {
+        MockServerSocketChannel testMSChnlnull = new MockServerSocketChannel(
+                null);
+        MockServerSocketChannel testMSChnl = new MockServerSocketChannel(
+                SelectorProvider.provider());
+        assertEquals(SelectionKey.OP_ACCEPT, this.serverChannel.validOps());
+        assertEquals(SelectionKey.OP_ACCEPT, testMSChnl.validOps());
+        assertEquals(SelectionKey.OP_ACCEPT, testMSChnlnull.validOps());
+
+    }
+
+    /*
+     * Test method for 'java.nio.channels.ServerSocketChannel.open()'
+     */
+    public void testOpen() {
+        MockServerSocketChannel testMSChnl = new MockServerSocketChannel(null);
+        MockServerSocketChannel testMSChnlnotnull = new MockServerSocketChannel(
+                SelectorProvider.provider());
+        assertEquals(SelectionKey.OP_ACCEPT, testMSChnlnotnull.validOps());
+        assertNull(testMSChnl.provider());
+        assertNotNull(testMSChnlnotnull.provider());
+        assertNotNull(this.serverChannel.provider());
+        assertEquals(testMSChnlnotnull.provider(), this.serverChannel
+                .provider());
+    }
+
+    // -------------------------------------------------------------------
+    // Test for socket()
+    // -------------------------------------------------------------------
+
+    /*
+     * Test method for 'java.nio.channels.ServerSocketChannel.socket()'
+     */
+    public void testSocket_Block_BeforeClose() throws Exception {
+        assertTrue(this.serverChannel.isOpen());
+        assertTrue(this.serverChannel.isBlocking());
+        ServerSocket s1 = this.serverChannel.socket();
+        assertFalse(s1.isClosed());
+        assertSocketNotAccepted(s1);
+        ServerSocket s2 = this.serverChannel.socket();
+        // same
+        assertSame(s1, s2);
+
+        // socket close makes the channel close
+        s1.close();
+        assertFalse(this.serverChannel.isOpen());
+
+    }
+
+    public void testSocket_NonBlock_BeforeClose() throws Exception {
+        assertTrue(this.serverChannel.isOpen());
+        this.serverChannel.configureBlocking(false);
+        ServerSocket s1 = this.serverChannel.socket();
+        assertFalse(s1.isClosed());
+        assertSocketNotAccepted(s1);
+        ServerSocket s2 = this.serverChannel.socket();
+        // same
+        assertSame(s1, s2);
+
+        // socket close makes the channel close
+        s1.close();
+        assertFalse(this.serverChannel.isOpen());
+
+    }
+
+    public void testSocket_Block_Closed() throws Exception {
+        this.serverChannel.close();
+        assertFalse(this.serverChannel.isOpen());
+        assertTrue(this.serverChannel.isBlocking());
+        ServerSocket s1 = this.serverChannel.socket();
+        assertTrue(s1.isClosed());
+        assertSocketNotAccepted(s1);
+        ServerSocket s2 = this.serverChannel.socket();
+        // same
+        assertSame(s1, s2);
+    }
+
+    public void testSocket_NonBlock_Closed() throws Exception {
+        this.serverChannel.configureBlocking(false);
+        this.serverChannel.close();
+        assertFalse(this.serverChannel.isBlocking());
+        assertFalse(this.serverChannel.isOpen());
+        ServerSocket s1 = this.serverChannel.socket();
+        assertTrue(s1.isClosed());
+        assertSocketNotAccepted(s1);
+        ServerSocket s2 = this.serverChannel.socket();
+        // same
+        assertSame(s1, s2);
+    }
+
+    private void assertSocketNotAccepted(ServerSocket s) throws IOException {
+        assertFalse(s.isBound());
+        assertNull(s.getInetAddress());
+        assertEquals(-1, s.getLocalPort());
+        assertNull(s.getLocalSocketAddress());
+        try {
+            assertEquals(0, s.getSoTimeout());
+        } catch (IOException expected) {
+            // Android doesn't cache the timeout, so the getsockopt(2) fails and throws.
+        }
+    }
+
+    public void testChannelBasicStatus() {
+        ServerSocket gotSocket = this.serverChannel.socket();
+        assertFalse(gotSocket.isClosed());
+        assertTrue(this.serverChannel.isBlocking());
+        assertFalse(this.serverChannel.isRegistered());
+        assertEquals(SelectionKey.OP_ACCEPT, this.serverChannel.validOps());
+        assertEquals(SelectorProvider.provider(), this.serverChannel.provider());
+    }
+
+    // -------------------------------------------------------------------
+    // Test for accept()
+    // -------------------------------------------------------------------
+
+    /*
+     * Test method for 'java.nio.channels.ServerSocketChannel.accept()'
+     */
+
+    public void testAccept_Block_NotYetBound() throws IOException {
+        assertTrue(this.serverChannel.isOpen());
+        assertTrue(this.serverChannel.isBlocking());
+        try {
+            this.serverChannel.accept();
+            fail("Should throw NotYetBoundException");
+        } catch (NotYetBoundException e) {
+            // correct
+        }
+    }
+
+    public void testAccept_NonBlock_NotYetBound() throws IOException {
+        assertTrue(this.serverChannel.isOpen());
+        this.serverChannel.configureBlocking(false);
+        try {
+            this.serverChannel.accept();
+            fail("Should throw NotYetBoundException");
+        } catch (NotYetBoundException e) {
+            // correct
+        }
+    }
+
+    public void testAccept_ClosedChannel() throws Exception {
+        this.serverChannel.close();
+        assertFalse(this.serverChannel.isOpen());
+        try {
+            this.serverChannel.accept();
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+    }
+
+    public void testAccept_Block_NoConnect() throws IOException {
+        assertTrue(this.serverChannel.isBlocking());
+        ServerSocket gotSocket = this.serverChannel.socket();
+        gotSocket.bind(localAddr1);
+        // blocking mode , will block and wait for ever...
+        // so must close the server channel with another thread.
+        new Thread() {
+            public void run() {
+                try {
+                    Thread.sleep(TIME_UNIT);
+                    ServerSocketChannelTest.this.serverChannel.close();
+                } catch (Exception e) {
+                    fail("Fail to close the server channel because of"
+                            + e.getClass().getName());
+                }
+            }
+        }.start();
+        try {
+            this.serverChannel.accept();
+            fail("Should throw a AsynchronousCloseException");
+        } catch (AsynchronousCloseException e) {
+            // OK.
+        }
+    }
+
+    public void testAccept_NonBlock_NoConnect() throws IOException {
+        ServerSocket gotSocket = this.serverChannel.socket();
+        gotSocket.bind(localAddr1);
+        this.serverChannel.configureBlocking(false);
+        // non-blocking mode , will immediately return
+        assertNull(this.serverChannel.accept());
+    }
+
+    /**
+     * @tests ServerSocketChannel#accept().socket()
+     */
+    public void test_read_Blocking_RealData() throws IOException {
+        serverChannel.socket().bind(localAddr1);
+        ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            buf.put((byte) i);
+        }
+        clientChannel.connect(localAddr1);
+        Socket serverSocket = serverChannel.accept().socket();
+        InputStream in = serverSocket.getInputStream();
+        buf.flip();
+        clientChannel.write(buf);
+        clientChannel.close();
+        assertReadResult(in,CAPACITY_NORMAL);
+    }
+
+    /**
+     * Asserts read content. The read content should contain <code>size</code>
+     * bytes, and the value should be a sequence from 0 to size-1
+     * ([0,1,...size-1]). Otherwise, the method throws Exception.
+     *
+     */
+    private void assertReadResult(InputStream in, int size) throws IOException{
+        byte[] readContent = new byte[size + 1];
+        int count = 0;
+        int total = 0;
+        while ((count = in.read(readContent, total, size + 1 - total)) != -1) {
+            total = total + count;
+        }
+        assertEquals(size, total);
+        for (int i = 0; i < size; i++) {
+            assertEquals((byte) i, readContent[i]);
+        }
+    }
+
+    /**
+     * @tests ServerSocketChannel#accept().socket()
+     */
+    public void test_read_NonBlocking_RealData() throws Exception {
+        serverChannel.configureBlocking(false);
+        serverChannel.socket().bind(localAddr1);
+        ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            buf.put((byte) i);
+        }
+        buf.flip();
+        clientChannel.connect(localAddr1);
+        Socket serverSocket = serverChannel.accept().socket();
+        InputStream in = serverSocket.getInputStream();
+        clientChannel.write(buf);
+        clientChannel.close();
+        assertReadResult(in,CAPACITY_NORMAL);
+    }
+
+    /**
+     * @tests ServerSocketChannel#accept().socket()
+     */
+    public void test_write_Blocking_RealData() throws IOException {
+        assertTrue(serverChannel.isBlocking());
+        ServerSocket serverSocket = serverChannel.socket();
+        serverSocket.bind(localAddr1);
+
+        byte[] writeContent = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < writeContent.length; i++) {
+            writeContent[i] = (byte) i;
+        }
+        clientChannel.connect(localAddr1);
+        Socket socket = serverChannel.accept().socket();
+        OutputStream out = socket.getOutputStream();
+        out.write(writeContent);
+        out.flush();
+        socket.close();
+        assertWriteResult(CAPACITY_NORMAL);
+    }
+
+
+    /**
+     * @tests ServerSocketChannel#accept().socket()
+     */
+    public void test_write_NonBlocking_RealData() throws Exception {
+        serverChannel.configureBlocking(false);
+        ServerSocket serverSocket = serverChannel.socket();
+        serverSocket.bind(localAddr1);
+
+        byte[] writeContent = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            writeContent[i] = (byte) i;
+        }
+        clientChannel.connect(localAddr1);
+        Socket clientSocket = serverChannel.accept().socket();
+        OutputStream out = clientSocket.getOutputStream();
+        out.write(writeContent);
+        clientSocket.close();
+        assertWriteResult(CAPACITY_NORMAL);
+    }
+
+    /**
+     * @throws InterruptedException
+     * @tests ServerSocketChannel#accept().socket()
+     */
+    public void test_read_LByteBuffer_Blocking_ReadWriteRealLargeData()
+            throws IOException, InterruptedException {
+        serverChannel.socket().bind(localAddr1);
+        ByteBuffer buf = ByteBuffer.allocate(CAPACITY_64KB);
+        for (int i = 0; i < CAPACITY_64KB; i++) {
+            buf.put((byte) i);
+        }
+        buf.flip();
+        clientChannel.connect(localAddr1);
+        WriteChannelThread writeThread = new WriteChannelThread(clientChannel, buf);
+        writeThread.start();
+        Socket socket = serverChannel.accept().socket();
+        InputStream in = socket.getInputStream();
+        assertReadResult(in,CAPACITY_64KB);
+        writeThread.join();
+        // check if the thread threw any exceptions
+        if (writeThread.exception != null) {
+            throw writeThread.exception;
+        }
+    }
+
+    class WriteChannelThread extends Thread {
+        SocketChannel channel;
+        ByteBuffer buffer;
+        IOException exception;
+
+        public WriteChannelThread(SocketChannel channel, ByteBuffer buffer) {
+            this.channel = channel;
+            this.buffer = buffer;
+        }
+
+        public void run() {
+            try {
+                channel.write(buffer);
+                channel.close();
+            } catch (IOException e) {
+                exception = e;
+            }
+        }
+    }
+
+    /**
+     * @tests ServerSocketChannel#accept().socket()
+     */
+    public void test_read_LByteBuffer_NonBlocking_ReadWriteRealLargeData()
+            throws Exception {
+        serverChannel.configureBlocking(false);
+        serverChannel.socket().bind(localAddr1);
+        ByteBuffer buf = ByteBuffer.allocate(CAPACITY_64KB);
+        for (int i = 0; i < CAPACITY_64KB; i++) {
+            buf.put((byte) i);
+        }
+        buf.flip();
+        clientChannel.connect(localAddr1);
+        WriteChannelThread writeThread = new WriteChannelThread(clientChannel, buf);
+        writeThread.start();
+        Socket socket = serverChannel.accept().socket();
+        InputStream in = socket.getInputStream();
+        assertReadResult(in,CAPACITY_64KB);
+        writeThread.join();
+        // check if the thread threw any exceptions
+        if (writeThread.exception != null) {
+            throw writeThread.exception;
+        }
+    }
+
+    /**
+     * @tests ServerSocketChannel#accept().socket()
+     */
+    public void test_write_LByteBuffer_NonBlocking_ReadWriteRealLargeData()
+            throws Exception {
+        serverChannel.configureBlocking(false);
+        serverChannel.socket().bind(localAddr1);
+        byte[] writeContent = new byte[CAPACITY_64KB];
+        for (int i = 0; i < writeContent.length; i++) {
+            writeContent[i] = (byte) i;
+        }
+        clientChannel.connect(localAddr1);
+        Socket socket = serverChannel.accept().socket();
+        WriteSocketThread writeThread = new WriteSocketThread(socket, writeContent);
+        writeThread.start();
+        assertWriteResult(CAPACITY_64KB);
+        writeThread.join();
+        // check if the thread threw any exceptions
+        if (writeThread.exception != null) {
+            throw writeThread.exception;
+        }
+    }
+
+    class WriteSocketThread extends Thread {
+        Socket socket;
+        byte[] buffer;
+        IOException exception;
+
+        public WriteSocketThread(Socket socket, byte[] buffer) {
+            this.socket = socket;
+            this.buffer = buffer;
+        }
+
+        public void run() {
+            try {
+                OutputStream out = socket.getOutputStream();
+                out.write(buffer);
+                socket.close();
+            } catch (IOException e) {
+                exception = e;
+            }
+        }
+    }
+
+    /**
+     * @tests ServerSocketChannel#accept().socket()
+     */
+    public void test_write_LByteBuffer_Blocking_ReadWriteRealLargeData()
+            throws Exception {
+        serverChannel.socket().bind(localAddr1);
+        byte[] writeContent = new byte[CAPACITY_64KB];
+        for (int i = 0; i < writeContent.length; i++) {
+            writeContent[i] = (byte) i;
+        }
+        clientChannel.connect(localAddr1);
+        Socket socket = serverChannel.accept().socket();
+        WriteSocketThread writeThread = new WriteSocketThread(socket, writeContent);
+        writeThread.start();
+        assertWriteResult(CAPACITY_64KB);
+        writeThread.join();
+        // check if the thread threw any exceptions
+        if (writeThread.exception != null) {
+            throw writeThread.exception;
+        }
+    }
+
+    /**
+     * Uses SocketChannel.read(ByteBuffer) to verify write result.
+     */
+    private void assertWriteResult(int size) throws IOException{
+        ByteBuffer buf = ByteBuffer.allocate(size + 1);
+        int count = 0;
+        int total = 0;
+        long beginTime = System.currentTimeMillis();
+        while ((count = clientChannel.read(buf)) != -1) {
+            total = total + count;
+            // 10s timeout to avoid dead loop
+            if (System.currentTimeMillis() - beginTime > 10000){
+                break;
+            }
+        }
+        assertEquals(total, size);
+        buf.flip();
+        for (int i = 0; i < count; i++) {
+            assertEquals((byte) i, buf.get(i));
+        }
+    }
+
+    /**
+     * @tests ServerSocketChannel#socket().getSoTimeout()
+     */
+    public void test_accept_SOTIMEOUT() throws IOException {
+        // regression test for Harmony-707
+        final int SO_TIMEOUT = 10;
+        ServerSocketChannel sc = ServerSocketChannel.open();
+        try {
+            ServerSocket ss = sc.socket();
+            ss.bind(localAddr1);
+            sc.configureBlocking(false);
+            ss.setSoTimeout(SO_TIMEOUT);
+            SocketChannel client = sc.accept();
+            // non blocking mode, returns null since there are no pending connections.
+            assertNull(client);
+            int soTimeout = ss.getSoTimeout();
+            // Harmony fails here.
+            assertEquals(SO_TIMEOUT, soTimeout);
+        } finally {
+            sc.close();
+        }
+    }
+
+    /**
+     * @tests ServerSocket#socket().accept()
+     */
+    public void test_socket_accept_Blocking_NotBound() throws IOException {
+        // regression test for Harmony-748
+        ServerSocket gotSocket = serverChannel.socket();
+        serverChannel.configureBlocking(true);
+        try {
+            gotSocket.accept();
+            fail("Should throw an IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+        serverChannel.close();
+        try {
+            gotSocket.accept();
+            fail("Should throw an IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests ServerSocket#socket().accept()
+     */
+    public void test_socket_accept_Nonblocking_NotBound() throws IOException {
+        // regression test for Harmony-748
+        ServerSocket gotSocket = serverChannel.socket();
+        serverChannel.configureBlocking(false);
+        try {
+            gotSocket.accept();
+            fail("Should throw an IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+        serverChannel.close();
+        try {
+            gotSocket.accept();
+            fail("Should throw an IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests ServerSocket#socket().accept()
+     */
+    public void test_socket_accept_Nonblocking_Bound() throws IOException {
+        // regression test for Harmony-748
+        serverChannel.configureBlocking(false);
+        ServerSocket gotSocket = serverChannel.socket();
+        gotSocket.bind(localAddr1);
+        try {
+            gotSocket.accept();
+            fail("Should throw an IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+        serverChannel.close();
+        try {
+            gotSocket.accept();
+            fail("Should throw a ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests ServerSocket#socket().accept()
+     */
+    public void test_socket_accept_Blocking_Bound() throws IOException {
+        // regression test for Harmony-748
+        serverChannel.configureBlocking(true);
+        ServerSocket gotSocket = serverChannel.socket();
+        gotSocket.bind(localAddr1);
+        serverChannel.close();
+        try {
+            gotSocket.accept();
+            fail("Should throw a ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+    /**
+     * Regression test for HARMONY-4961
+     */
+    public void test_socket_getLocalPort() throws IOException {
+        serverChannel.socket().bind(localAddr1);
+        clientChannel.connect(localAddr1);
+        SocketChannel myChannel = serverChannel.accept();
+        int port = myChannel.socket().getLocalPort();
+        assertEquals(localAddr1.getPort(), port);
+        myChannel.close();
+        clientChannel.close();
+        serverChannel.close();
+    }
+
+    /**
+     * Regression test for HARMONY-6375
+     */
+    public void test_accept_configureBlocking() throws Exception {
+        InetSocketAddress localAddr = new InetSocketAddress("localhost", 0);
+        serverChannel.socket().bind(localAddr);
+
+        // configure the channel non-blocking
+        // when it is accepting in main thread
+        new Thread() {
+            public void run() {
+                try {
+                    Thread.sleep(TIME_UNIT);
+                    serverChannel.configureBlocking(false);
+                    serverChannel.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }.start();
+
+        try {
+            serverChannel.accept();
+            fail("should throw AsynchronousCloseException");
+        } catch (AsynchronousCloseException e) {
+            // expected
+        }
+        serverChannel.close();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SinkChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SinkChannelTest.java
new file mode 100644
index 0000000..9e96fad
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SinkChannelTest.java
@@ -0,0 +1,505 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for Pipe.SinkChannel class
+ */
+public class SinkChannelTest extends TestCase {
+
+	private static final int BUFFER_SIZE = 5;
+
+	private static final String ISO8859_1 = "ISO8859-1";
+
+	private Pipe pipe;
+
+	private Pipe.SinkChannel sink;
+
+	private Pipe.SourceChannel source;
+
+	private ByteBuffer buffer;
+
+	private ByteBuffer positionedBuffer;
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		pipe = Pipe.open();
+		sink = pipe.sink();
+		source = pipe.source();
+		buffer = ByteBuffer.wrap("bytes".getBytes(ISO8859_1));
+		positionedBuffer = ByteBuffer.wrap("12345bytes".getBytes(ISO8859_1));
+		positionedBuffer.position(BUFFER_SIZE);
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SinkChannel#validOps()
+	 */
+	public void test_validOps() {
+		assertEquals(SelectionKey.OP_WRITE, sink.validOps());
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+	 */
+	public void test_write_LByteBuffer() throws IOException {
+		ByteBuffer[] bufArray = { buffer, positionedBuffer };
+		boolean[] sinkBlockingMode = { true, true, false, false };
+		boolean[] sourceBlockingMode = { true, false, true, false };
+		int oldPosition;
+		int currentPosition;
+		for (int i = 0; i < sinkBlockingMode.length; ++i) {
+			sink.configureBlocking(sinkBlockingMode[i]);
+			source.configureBlocking(sourceBlockingMode[i]);
+			// if sink and source both are blocking mode, source only needs read
+			// once to get what sink write.
+			boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
+			for (ByteBuffer buf : bufArray) {
+				buf.mark();
+				oldPosition = buf.position();
+				sink.write(buf);
+				ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+				int totalCount = 0;
+				do {
+					int count = source.read(readBuf);
+					if (count > 0) {
+						totalCount += count;
+					}
+				} while (totalCount != BUFFER_SIZE && !isBlocking);
+				currentPosition = buf.position();
+				assertEquals(BUFFER_SIZE, currentPosition - oldPosition);
+				assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
+				buf.reset();
+			}
+		}
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+	 */
+	public void test_write_LByteBuffer_mutliThread() throws IOException,
+	        InterruptedException {
+        final int THREAD_NUM = 20;
+        final byte[] strbytes = "bytes".getBytes(ISO8859_1);
+        Thread[] thread = new Thread[THREAD_NUM];
+        for (int i = 0; i < THREAD_NUM; i++) {
+            thread[i] = new Thread() {
+                public void run() {
+                    try {
+                        sink.write(ByteBuffer.wrap(strbytes));
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            };
+        }
+        for (int i = 0; i < THREAD_NUM; i++) {
+            thread[i].start();
+        }
+        for (int i = 0; i < THREAD_NUM; i++) {
+            thread[i].join();
+        }
+        ByteBuffer readBuf = ByteBuffer.allocate(THREAD_NUM * BUFFER_SIZE);
+
+        long totalCount = 0;
+        do {
+            long count = source.read(readBuf);
+            if (count < 0) {
+                break;
+            }
+            totalCount += count;
+        } while (totalCount != (THREAD_NUM * BUFFER_SIZE));
+
+        StringBuffer buf = new StringBuffer();
+        for (int i = 0; i < THREAD_NUM; i++) {
+            buf.append("bytes");
+        }
+        String readString = buf.toString();
+        assertEquals(readString, new String(readBuf.array(), ISO8859_1));
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+	 */
+	public void test_write_LByteBuffer_Exception() throws IOException {
+		// write null ByteBuffer
+		ByteBuffer nullBuf = null;
+		try {
+			sink.write(nullBuf);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+    public void test_write_LByteBuffer_SourceClosed() throws IOException {
+        source.close();
+        try {
+            int written = sink.write(buffer);
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void test_write_LByteBuffer_SinkClosed() throws IOException {
+        sink.close();
+        try {
+            sink.write(buffer);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+	/**
+	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
+	 */
+	public void test_write_$LByteBuffer() throws IOException {
+		ByteBuffer[] bufArray = { buffer, positionedBuffer };
+		boolean[] sinkBlockingMode = { true, true, false, false };
+		boolean[] sourceBlockingMode = { true, false, true, false };
+		for (int i = 0; i < sinkBlockingMode.length; ++i) {
+			sink.configureBlocking(sinkBlockingMode[i]);
+			source.configureBlocking(sourceBlockingMode[i]);
+			buffer.position(0);
+			positionedBuffer.position(BUFFER_SIZE);
+			sink.write(bufArray);
+			// if sink and source both are blocking mode, source only needs read
+			// once to get what sink write.
+			boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
+			for (int j = 0; j < bufArray.length; ++j) {
+				ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+				int totalCount = 0;
+				do {
+					int count = source.read(readBuf);
+					if (count < 0) {
+						break;
+					}
+					totalCount += count;
+				} while (totalCount != BUFFER_SIZE && !isBlocking);
+				assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
+			}
+			assertEquals(BUFFER_SIZE, buffer.position());
+			assertEquals(10, positionedBuffer.position());
+		}
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
+	 */
+	public void test_write_$LByteBuffer_Exception() throws IOException {
+		// write null ByteBuffer[]
+		ByteBuffer[] nullBufArrayRef = null;
+		try {
+			sink.write(nullBufArrayRef);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+
+		// write ByteBuffer[] contains null element
+		ByteBuffer nullBuf = null;
+		ByteBuffer[] nullBufArray = { buffer, nullBuf };
+		try {
+			sink.write(nullBufArray);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+    public void test_write_$LByteBuffer_SourceClosed() throws IOException {
+        ByteBuffer[] bufArray = { buffer };
+        source.close();
+        try {
+            long written = sink.write(bufArray);
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+	/**
+	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
+	 */
+	public void test_write_$LByteBuffer_SinkClosed() throws IOException {
+		ByteBuffer[] bufArray = { buffer };
+		sink.close();
+		try {
+			sink.write(bufArray);
+			fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+
+		ByteBuffer[] nullBufArrayRef = null;
+		try {
+			sink.write(nullBufArrayRef);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+
+		ByteBuffer nullBuf = null;
+		ByteBuffer[] nullBufArray = { nullBuf };
+		// write ByteBuffer[] contains null element
+		try {
+			sink.write(nullBufArray);
+			fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[], int, int)
+	 */
+	public void test_write_$LByteBufferII() throws IOException {
+		ByteBuffer[] bufArray = { buffer, positionedBuffer };
+		boolean[] sinkBlockingMode = { true, true, false, false };
+		boolean[] sourceBlockingMode = { true, false, true, false };
+		for (int i = 0; i < sinkBlockingMode.length; ++i) {
+			sink.configureBlocking(sinkBlockingMode[i]);
+			source.configureBlocking(sourceBlockingMode[i]);
+			positionedBuffer.position(BUFFER_SIZE);
+			sink.write(bufArray, 1, 1);
+			// if sink and source both are blocking mode, source only needs read
+			// once to get what sink write.
+			boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
+			ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+			int totalCount = 0;
+			do {
+				int count = source.read(readBuf);
+				if (count < 0) {
+					break;
+				}
+				totalCount += count;
+			} while (totalCount != BUFFER_SIZE && !isBlocking);
+			assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
+			assertEquals(10, positionedBuffer.position());
+		}
+	}
+
+    public void test_write_$LByteBufferII_Exception() throws IOException {
+        try {
+            sink.write(null, 0, 1);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            sink.write(new ByteBuffer[2], 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+
+        // write ByteBuffer[] contains null element
+        ByteBuffer nullBuf = null;
+        ByteBuffer[] nullBufArray = { nullBuf };
+        try {
+            sink.write(nullBufArray, 0, 1);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        try {
+            sink.write(nullBufArray, 0, -1);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        ByteBuffer[] bufArray = { buffer, nullBuf };
+        try {
+            sink.write(bufArray, 0, -1);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sink.write(bufArray, -1, 0);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sink.write(bufArray, -1, 1);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sink.write(bufArray, 0, 3);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sink.write(bufArray, 0, 2);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+    }
+
+    public void test_write_$LByteBufferII_SourceClosed() throws IOException {
+        ByteBuffer[] bufArray = { buffer };
+        source.close();
+
+        try {
+            long written = sink.write(bufArray, 0, 1);
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void test_write_$LByteBufferII_SinkClosed() throws IOException {
+        ByteBuffer[] bufArray = { buffer };
+        sink.close();
+        try {
+            sink.write(bufArray, 0, 1);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+
+        try {
+            sink.write(null, 0, 1);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            sink.write(new ByteBuffer[2], 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+
+        // write ByteBuffer[] contains null element
+        ByteBuffer nullBuf = null;
+        ByteBuffer[] nullBufArray = { nullBuf };
+        try {
+            sink.write(nullBufArray, 0, 1);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+        // illegal array index
+        try {
+            sink.write(nullBufArray, 0, -1);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        ByteBuffer[] bufArray2 = { buffer, nullBuf };
+        // illegal array index
+        try {
+            sink.write(bufArray2, 0, -1);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sink.write(bufArray2, -1, 0);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sink.write(bufArray2, -1, 1);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sink.write(bufArray2, 0, 3);
+            fail("should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        try {
+            sink.write(bufArray2, 0, 2);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+    }
+
+    public void test_close() throws IOException {
+        sink.close();
+        assertFalse(sink.isOpen());
+    }
+
+    public void test_socketChannel_read_close() throws Exception {
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+        SocketChannel sc = SocketChannel.open();
+        ByteBuffer buf = null;
+        try{
+            sc.write(buf);
+            fail("should throw NPE");
+        }catch (NullPointerException e){
+            // expected
+        }
+        sc.connect(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+        SocketChannel sock = ssc.accept();
+        ssc.close();
+        sc.close();
+        try{
+            sc.write(buf);
+            fail("should throw NPE");
+        }catch (NullPointerException e){
+            // expected
+        }
+        sock.close();
+    }
+
+    public void test_socketChannel_read_write() throws Exception {
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+        SocketChannel sc = SocketChannel.open();
+        sc.connect(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+        SocketChannel sock = ssc.accept();
+        ByteBuffer[] buf = {ByteBuffer.allocate(10),null};
+        try {
+            sc.write(buf,0,2);
+            fail("should throw NPE");
+        } catch (NullPointerException expected) {
+        }
+        ssc.close();
+        sc.close();
+        ByteBuffer target = ByteBuffer.allocate(10);
+        assertEquals(-1, sock.read(target));
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
new file mode 100644
index 0000000..7325ba1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
@@ -0,0 +1,3628 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.BindException;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/**
+ * Tests for SocketChannel and its default implementation.
+ */
+public class SocketChannelTest extends TestCase {
+
+    private static final int CAPACITY_NORMAL = 200;
+
+    private InetSocketAddress localAddr1;
+
+    private InetSocketAddress localAddr2;
+
+    private SocketChannel channel1;
+
+    private SocketChannel channel2;
+
+    private ServerSocket server1;
+
+    private ServerSocket server2;
+
+    private final static int TIMEOUT = 60000;
+
+    private final static int EOF = -1;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.localAddr1 = new InetSocketAddress("127.0.0.1",
+                Support_PortManager.getNextPort());
+        this.localAddr2 = new InetSocketAddress("127.0.0.1",
+                Support_PortManager.getNextPort());
+        this.channel1 = SocketChannel.open();
+        this.channel2 = SocketChannel.open();
+        this.server1 = new ServerSocket(localAddr1.getPort());
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        if (null != this.channel1) {
+            try {
+                this.channel1.close();
+            } catch (Exception e) {
+                //ignore
+            }
+        }
+        if (null != this.channel2) {
+            try {
+                this.channel2.close();
+            } catch (Exception e) {
+                //ignore
+            }
+        }
+        if (null != this.server1) {
+            try {
+                this.server1.close();
+            } catch (Exception e) {
+                //ignore
+            }
+        }
+        if (null != this.server2) {
+            try {
+                this.server2.close();
+            } catch (Exception e) {
+                //ignore
+            }
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Test for methods in abstract class.
+    // -------------------------------------------------------------------
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.validOps()'
+     */
+    public void testValidOps() {
+        MockSocketChannel testMSChannel = new MockSocketChannel(null);
+        assertEquals(13, this.channel1.validOps());
+        assertEquals(13, testMSChannel.validOps());
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.open()'
+     */
+    public void testOpen() throws IOException {
+        java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[1];
+        buf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        MockSocketChannel testMSChannel = new MockSocketChannel(null);
+        MockSocketChannel testMSChannelnotnull = new MockSocketChannel(
+                SelectorProvider.provider());
+        assertNull(testMSChannel.provider());
+        assertNotNull(testMSChannelnotnull.provider());
+        assertNotNull(this.channel1);
+        assertEquals(this.channel1.provider(), testMSChannelnotnull.provider());
+        try {
+            this.channel1.write(buf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.open(SocketAddress)'
+     */
+    public void testOpenSocketAddress_Null() throws IOException {
+        SocketChannel channel1IP = null;
+        try {
+            channel1IP = SocketChannel.open(null);
+            fail("Should throw an IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // correct
+        }
+        assertNull(channel1IP);
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.read(ByteBuffer[])'
+     */
+    public void testReadByteBufferArray() throws IOException {
+        java.nio.ByteBuffer[] byteBuf = null;
+        MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+        MockSocketChannel testMSChannel = new MockSocketChannel(
+                SelectorProvider.provider());
+        ServerSocket testServer = new ServerSocket(Support_PortManager
+                .getNextPort());
+        try {
+            try {
+                this.channel1.read(byteBuf);
+                fail("Should throw NPE");
+            } catch (NullPointerException e) {
+                // correct
+            }
+            byteBuf = new java.nio.ByteBuffer[CAPACITY_NORMAL];
+            try {
+                this.channel1.read(byteBuf);
+                fail("Should throw NotYetConnectedException");
+            } catch (NotYetConnectedException e) {
+                // correct
+            }
+            long readNum = CAPACITY_NORMAL;
+            readNum = testMSChannel.read(byteBuf);
+            assertEquals(0, readNum);
+            readNum = CAPACITY_NORMAL;
+            readNum = testMSChannelnull.read(byteBuf);
+            assertEquals(0, readNum);
+        } finally {
+            testServer.close();
+        }
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.read(ByteBuffer[])'
+     */
+    public void testReadByteBufferArray_BufNull() throws IOException {
+        java.nio.ByteBuffer[] byteBuf = null;
+        MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+        MockSocketChannel testMSChannel = new MockSocketChannel(
+                SelectorProvider.provider());
+        try {
+            this.channel1.read(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            testMSChannel.read(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            testMSChannelnull.read(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.write(ByteBuffer[])'
+     */
+    public void testWriteByteBufferArray() throws IOException {
+        java.nio.ByteBuffer[] byteBuf = null;
+        MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+        MockSocketChannel testMSChannel = new MockSocketChannel(
+                SelectorProvider.provider());
+        try {
+            this.channel1.write(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        byteBuf = new java.nio.ByteBuffer[CAPACITY_NORMAL];
+        try {
+            this.channel1.write(byteBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        testMSChannel.write(byteBuf);
+        testMSChannelnull.write(byteBuf);
+    }
+
+    /*
+     * Test method for 'java.nio.channels.SocketChannel.write(ByteBuffer[])'
+     */
+    public void testWriteByteBufferArray_BufNull() throws IOException {
+        java.nio.ByteBuffer[] byteBuf = null;
+        MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+        MockSocketChannel testMSChannel = new MockSocketChannel(
+                SelectorProvider.provider());
+        try {
+            this.channel1.write(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            testMSChannel.write(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            testMSChannelnull.write(byteBuf);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    public void testSocket_BasicStatusBeforeConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        Socket s1 = this.channel1.socket();
+        assertSocketBeforeConnect(s1);
+        Socket s2 = this.channel1.socket();
+        // same
+        assertSame(s1, s2);
+    }
+
+    public void testSocket_Block_BasicStatusAfterConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        assertTrue(this.channel1.connect(localAddr1));
+
+        assertTrue(this.channel1.isConnected());
+        Socket s1 = this.channel1.socket();
+
+        assertSocketAfterConnect(s1, localAddr1);
+        Socket s2 = this.channel1.socket();
+        // same
+        assertSame(s1, s2);
+    }
+
+    public void testSocket_NonBlock_BasicStatusAfterConnect() throws Exception {
+        assertFalse(this.channel1.isConnected());// not connected
+        this.channel1.configureBlocking(false);
+        boolean connected = channel1.connect(localAddr1);
+        Socket s1 = null;
+        Socket s2 = null;
+        if (!connected) {
+            assertFalse(this.channel1.isConnected());
+            assertTrue(this.channel1.isConnectionPending());
+            s1 = this.channel1.socket();
+            // status of not connected
+            assertSocketBeforeConnect(s1);
+            s2 = this.channel1.socket();
+            // same
+            assertSame(s1, s2);
+        }
+
+        if (tryFinish()) {
+            assertTrue(this.channel1.isConnected());
+            s1 = this.channel1.socket();
+            assertSocketAfterConnect(s1, localAddr1);
+            s2 = this.channel1.socket();
+            // same
+            assertSame(s1, s2);
+        }
+    }
+
+    public void testSocket_Block_ActionsBeforeConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        Socket s = this.channel1.socket();
+        assertSocketAction_Block_BeforeConnect(s);
+    }
+
+    public void testSocket_Block_ActionsAfterConnect() throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        assertTrue(this.channel1.connect(localAddr1));
+        assertTrue(this.channel1.isConnected());
+        Socket s = this.channel1.socket();
+        assertSocketAction_Block_AfterConnect(s);
+
+    }
+
+    public void testSocket_NonBlock_ActionsAfterConnectBeforeFinish()
+            throws IOException {
+        assertFalse(this.channel1.isConnected());// not connected
+        this.channel1.configureBlocking(false);
+        boolean connected = channel1.connect(localAddr1);
+        if (!connected) {
+            assertFalse(this.channel1.isConnected());
+            assertTrue(this.channel1.isConnectionPending());
+            Socket s1 = this.channel1.socket();
+            // Action of not connected
+            assertSocketAction_NonBlock_BeforeConnect(s1);
+            Socket s2 = this.channel1.socket();
+            // same
+            assertSame(s1, s2);
+        }
+    }
+
+    public void testSocket_NonBlock_ActionsAfterConnectAfterFinish()
+            throws Exception {
+        assertFalse(this.channel1.isConnected());// not connected
+        this.channel1.configureBlocking(false);
+        channel1.connect(localAddr1);
+        if (tryFinish()) {
+            Socket s1 = this.channel1.socket();
+            assertSocketAction_NonBlock_AfterConnect(s1);
+            Socket s2 = this.channel1.socket();
+            // same
+            assertSame(s1, s2);
+        }
+    }
+
+    public void testSocket_getInetAddress() throws Exception {
+        Socket socket = channel1.socket();
+        assertNull(socket.getInetAddress());
+
+        channel1.connect(localAddr1);
+
+        assertNotNull(socket.getInetAddress());
+        assertEquals(localAddr1.getAddress(), socket.getInetAddress());
+    }
+
+    public void testSocket_getRemoteSocketAddress() throws Exception {
+        Socket socket = channel1.socket();
+        assertNull(socket.getRemoteSocketAddress());
+
+        channel1.connect(localAddr1);
+
+        assertNotNull(socket.getRemoteSocketAddress());
+        assertEquals(localAddr1, socket.getRemoteSocketAddress());
+    }
+
+    public void testSocket_getPort() throws Exception {
+        Socket socket = channel1.socket();
+        assertEquals(0, socket.getPort());
+
+        channel1.connect(localAddr1);
+
+        assertEquals(localAddr1.getPort(), socket.getPort());
+    }
+
+    public void testSocket_getLocalAddress() throws Exception {
+        Socket socket = channel1.socket();
+        assertNotNull(socket.getLocalAddress());
+
+        channel1.connect(localAddr1);
+
+        assertNotNull(socket.getLocalAddress());
+    }
+
+    public void testSocket_getLocalSocketAddress() throws Exception {
+        Socket socket = channel1.socket();
+        assertNull(socket.getLocalSocketAddress());
+
+        channel1.connect(localAddr1);
+
+        assertNotNull(socket.getLocalSocketAddress());
+    }
+
+    public void testSocket_getLocalPort() throws Exception {
+        Socket socket = channel1.socket();
+        assertEquals(-1, socket.getLocalPort());
+
+        channel1.connect(localAddr1);
+
+        assertTrue(-1 != socket.getLocalPort());
+        assertTrue(0 != socket.getLocalPort());
+    }
+
+    public void testSocket_bind() throws Exception {
+        Socket socket = channel1.socket();
+        socket.bind(new InetSocketAddress("127.0.0.1", 0));
+        assertEquals("127.0.0.1", socket.getLocalAddress().getHostAddress());
+        assertTrue(socket.getLocalPort() != -1);
+    }
+
+    private void assertSocketBeforeConnect(Socket s) throws IOException {
+        assertFalse(s.isBound());
+        assertFalse(s.isClosed());
+        assertFalse(s.isConnected());
+        assertFalse(s.getKeepAlive());
+        try {
+            s.getInputStream();
+            fail("Should throw SocketException.");
+        } catch (SocketException e) {
+            // OK.
+        }
+        assertFalse(s.getOOBInline());
+        try {
+            s.getOutputStream();
+            fail("Should throw SocketException.");
+        } catch (SocketException e) {
+            // OK.
+        }
+        assertEquals(-1, s.getSoLinger());
+        assertFalse(s.getTcpNoDelay());
+
+        assertFalse(s.isInputShutdown());
+        assertFalse(s.isOutputShutdown());
+
+        assertNull(s.getInetAddress());
+        assertEquals(s.getLocalAddress().getHostAddress(), "0.0.0.0");
+        // RI fails here. RI returns 0 while spec says unbound socket should
+        // return -1.
+        assertEquals(-1, s.getLocalPort());
+        assertFalse(s.getReuseAddress());
+        assertNull(s.getLocalSocketAddress());
+
+        // not connected
+        assertEquals(0, s.getPort());
+        assertTrue(s.getReceiveBufferSize() >= 8192);
+        assertNull(s.getRemoteSocketAddress());
+        assertTrue(s.getSendBufferSize() >= 8192);
+        assertEquals(0, s.getSoTimeout());
+        assertEquals(0, s.getTrafficClass());
+
+    }
+
+    private void assertSocketAfterConnect(Socket s, InetSocketAddress address)
+            throws IOException {
+        assertTrue(s.isBound());
+        assertFalse(s.isClosed());
+        assertTrue(s.isConnected());
+        assertFalse(s.getKeepAlive());
+
+        assertNotNull(s.getInputStream());
+        assertNotNull(s.getOutputStream());
+
+        assertFalse(s.getOOBInline());
+        assertEquals(-1, s.getSoLinger());
+        assertFalse(s.getTcpNoDelay());
+
+        assertFalse(s.isInputShutdown());
+        assertFalse(s.isOutputShutdown());
+
+        assertSame(s.getInetAddress(), address.getAddress());
+
+        assertEquals(s.getLocalAddress(), this.localAddr1.getAddress());
+        assertEquals(s.getPort(), address.getPort());
+        assertNotNull(s.getLocalSocketAddress());
+        assertTrue(s.getReceiveBufferSize() >= 8192);
+        assertEquals(s.getRemoteSocketAddress(), (SocketAddress) address);
+        // assertFalse(s.getReuseAddress());
+        assertTrue(s.getSendBufferSize() >= 8192);
+        assertEquals(0, s.getSoTimeout());
+        assertEquals(0, s.getTrafficClass());
+    }
+
+    private void assertSocketAction_Block_BeforeConnect(Socket s)
+            throws IOException {
+        assertFalse(this.channel1.isConnected());
+        this.server2 = new ServerSocket(localAddr2.getPort());
+        s.connect(localAddr2);
+        assertTrue(this.channel1.isConnected());
+        assertTrue(s.isConnected());
+
+        assertSocketAfterConnect(s, localAddr2);
+
+        try {
+            s.bind(localAddr2);
+            fail("Should throw AlreadyConnectedException");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+
+        s.close();
+        assertTrue(s.isClosed());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    private void assertSocketAction_NonBlock_BeforeConnect(Socket s)
+            throws IOException {
+        assertFalse(this.channel1.isConnected());
+        this.server2 = new ServerSocket(localAddr2.getPort());
+        try {
+            s.connect(localAddr2);
+            fail("Should throw IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e1) {
+            // OK.
+        }
+
+        if (this.channel1.isConnectionPending()) {
+            try {
+                s.bind(localAddr2);
+                fail("Should throw ConnectionPendingException");
+            } catch (ConnectionPendingException e1) {
+                // OK.
+            }
+        } else {
+            try {
+                s.bind(localAddr2);
+                fail("Should throw BindException");
+            } catch (BindException e1) {
+                // OK.
+            }
+        }
+
+        assertFalse(this.channel1.isConnected());
+        assertFalse(s.isConnected());
+
+        s.close();
+        assertTrue(s.isClosed());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    private void assertSocketAction_Block_AfterConnect(Socket s)
+            throws IOException {
+        assertEquals(s.getPort(), localAddr1.getPort());
+        assertTrue(this.channel1.isConnected());
+        assertTrue(s.isConnected());
+        try {
+            s.connect(localAddr2);
+            fail("Should throw AlreadyConnectedException");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+
+        try {
+            s.bind(localAddr2);
+            fail("Should throw AlreadyConnectedException");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+
+        s.close();
+        assertTrue(s.isClosed());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    private void assertSocketAction_NonBlock_AfterConnect(Socket s)
+            throws IOException {
+        assertEquals(s.getPort(), localAddr1.getPort());
+        assertTrue(this.channel1.isConnected());
+        assertTrue(s.isConnected());
+
+        if (this.channel1.isConnectionPending()) {
+            try {
+                s.connect(localAddr2);
+                fail("Should throw AlreadyConnectedException");
+            } catch (AlreadyConnectedException e) {
+                // OK.
+            }
+        } else {
+            try {
+                s.connect(localAddr2);
+                fail("Should throw IllegalBlockingModeException");
+            } catch (IllegalBlockingModeException e) {
+                // OK.
+            }
+        }
+
+        try {
+            s.bind(localAddr2);
+            fail("Should throw AlreadyConnectedException");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+
+        s.close();
+        assertTrue(s.isClosed());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    // -------------------------------------------------------------------
+    // Tests for connect(), finishConnect(),isConnected(),isConnectionPending()
+    // These methods are very close, so we test them together, call them "CFII".
+    // -------------------------------------------------------------------
+    /**
+     * connect-->finish-->close
+     */
+    public void testCFII_Norml_NoServer_Block() throws Exception {
+        // ensure
+        ensureServerClosed();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectException here.");
+        } catch (ConnectException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw a ClosedChannelException here.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * connect-->finish-->close
+     */
+    public void testCFII_Norml_NoServer_NonBlock() throws Exception {
+        connectNoServerNonBlock();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->close
+     */
+    public void testCFII_Norml_Server_Block() throws Exception {
+        connectServerBlock();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->finish-->close
+     */
+    public void testCFII_Norml_Server_NonBlock() throws Exception {
+        connectServerNonBlock();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->server closed-->finish-->close
+     */
+    public void testCFII_ServerClosed_Block() throws Exception {
+        // ensure
+        ensureServerOpen();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        assertTrue(this.channel1.connect(localAddr1));
+        statusConnected_NotPending();
+
+        ensureServerClosed();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->server closed-->finish-->close
+     */
+    public void testCFII_ServerClosed_NonBlock() throws Exception {
+        // ensure
+        ensureServerOpen();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        boolean connected = channel1.connect(localAddr1);
+        if (!connected) {
+            statusNotConnected_Pending();
+        }
+        ensureServerClosed();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->server closed-->close
+     */
+    public void testCFII_ServerClosedAfterFinish_Block() throws Exception {
+        connectServerBlock();
+
+        ensureServerClosed();
+        assertTrue(this.channel1.isOpen());
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->finish-->server closed-->close
+     */
+    public void testCFII_ServerClosedAfterFinish_NonBlock() throws Exception {
+        connectServerNonBlock();
+
+        ensureServerClosed();
+        assertTrue(this.channel1.isOpen());
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * no server-->connect-->server open-->finish-->close
+     */
+    public void testCFII_ServerStartLater_Block() throws Exception {
+        // ensure
+        ensureServerClosed();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectException here.");
+        } catch (ConnectException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        ensureServerOpen();
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw a ClosedChannelException here.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+    }
+
+    /**
+     * no server-->connect-->server open-->finish-->close
+     */
+    public void testCFII_ServerStartLater_NonBlock() throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+
+        ensureServerOpen();
+
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            this.channel1.close();
+        } catch (ConnectException e) {
+            // FIXME: assertEquals(e.getMessage(), "Connection refused");
+        }
+    }
+
+    /**
+     * connect-->finish-->finish-->close
+     */
+    public void testCFII_FinishTwice_NoServer_NonBlock() throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            this.channel1.close();
+        } catch (ConnectException e) {
+          // FIXME: assertEquals(e.getMessage(), "Connection refused");
+        }
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->finish-->close
+     */
+    public void testCFII_FinishTwice_Server_Block() throws Exception {
+        connectServerBlock();
+        tryFinish();
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->finish-->finish-->close
+     */
+    public void testCFII_FinishTwice_Server_NonBlock() throws Exception {
+        connectServerNonBlock();
+        tryFinish();
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->connect-->close
+     */
+    public void testCFII_ConnectAfterFinish_NoServer_Block() throws Exception {
+        // ensure
+        ensureServerClosed();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectException here.");
+        } catch (ConnectException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw a ClosedChannelException here.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ClosedChannelException here.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->connect-->close
+     */
+    public void testCFII_ConnectAfterFinish_NoServer_NonBlock()
+            throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+        } catch (ConnectException e) {
+            // FIXME: assertEquals(e.getMessage(), "Connection refused");
+        }
+
+        if (this.channel1.isOpen()) {
+
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw a ConnectionPendingException here.");
+            } catch (ConnectionPendingException e) {
+                // OK.
+            }
+            statusNotConnected_Pending();
+
+            // connect another addr
+            try {
+                this.channel1.connect(localAddr2);
+                fail("Should throw a ConnectionPendingException here.");
+            } catch (ConnectionPendingException e) {
+                // OK.
+            }
+            statusNotConnected_Pending();
+
+            // connect if server closed
+            ensureServerClosed();
+
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw a ConnectionPendingException here.");
+            } catch (ConnectionPendingException e) {
+                // OK.
+            }
+            statusNotConnected_Pending();
+
+            this.channel1.close();
+        }
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->finish-->connect-->close
+     */
+    public void testCFII_ConnectAfterFinish_Server_Block() throws Exception {
+        connectServerBlock();
+
+        if (!this.channel1.isConnected()) {
+            System.err
+                    .println("Connection fail, testCFII_ConnectAfterFinish_Server_Block is not finished.");
+            return;
+        }
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw an AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        // connect another addr
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw an AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        // connect if server closed
+        ensureServerClosed();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw an AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->finish-->connect-->close
+     */
+    public void testCFII_ConnectAfterFinish_Server_NonBlock() throws Exception {
+        connectServerNonBlock();
+
+        if (!this.channel1.isConnected()) {
+            System.err
+                    .println("Connection fail, testCFII_ConnectAfterFinish_Server_Block is not finished.");
+            return;
+        }
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw an AlreadyConnectedException or a ConnectionPendingException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+
+        statusConnected_NotPending();
+
+        // connect another addr
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw an AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        // connect if server closed
+        ensureServerClosed();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw an AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->connect-->finish-->close
+     */
+    public void testCFII_ConnectTwice_NoServer_NonBlock() throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectionPendingException here.");
+        } catch (ConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_Pending();
+
+        // connect another addr
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw a ConnectionPendingException here.");
+        } catch (ConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_Pending();
+
+        // connect if server closed
+        ensureServerClosed();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectionPendingException here.");
+        } catch (ConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_Pending();
+
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            this.channel1.close();
+        } catch (ConnectException e) {
+            // FIXME: assertEquals(e.getMessage(), "Connection refused");
+        }
+
+        statusChannelClosed();
+    }
+
+    /**
+     * connect-->connect-->finish-->close
+     */
+    public void testCFII_ConnectTwice_Server_Block() throws Exception {
+        // ensure
+        ensureServerOpen();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        assertTrue(this.channel1.connect(localAddr1));
+        statusConnected_NotPending();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw an AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        // connect another addr
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw an AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        // connect if server closed
+        ensureServerClosed();
+
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw an AlreadyConnectedException here.");
+        } catch (AlreadyConnectedException e) {
+            // OK.
+        }
+        statusConnected_NotPending();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * connect-->connect-->finish-->close
+     */
+    public void testCFII_ConnectTwice_Server_NonBlock() throws Exception {
+        // ensure
+        ensureServerOpen();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        boolean connected = channel1.connect(localAddr1);
+        if (!connected) {
+            statusNotConnected_Pending();
+
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw a ConnectionPendingException here.");
+            } catch (ConnectionPendingException e) {
+                // OK.
+            }
+            statusNotConnected_Pending();
+
+            // connect another addr
+            try {
+                this.channel1.connect(localAddr2);
+                fail("Should throw a ConnectionPendingException here.");
+            } catch (ConnectionPendingException e) {
+                // OK.
+            }
+            statusNotConnected_Pending();
+
+            // connect if server closed
+            ensureServerClosed();
+
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw a ConnectionPendingException here.");
+            } catch (ConnectionPendingException e) {
+                // OK.
+            }
+            statusNotConnected_Pending();
+        }
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    /**
+     * finish-->connect-->finish-->close
+     */
+    public void testCFII_FinishFirst_NoServer_Block() throws Exception {
+        // ensure
+        ensureServerClosed();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // finish
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_NotPending();
+        // connect
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw a ConnectException here.");
+        } catch (ConnectException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw a ClosedChannelException here.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+    }
+
+    /**
+     * finish-->connect-->finish-->close
+     */
+    public void testCFII_FinishFirst_NoServer_NonBlock() throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // finish
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            this.channel1.close();
+        } catch (ConnectException e) {
+            // FIXME: assertEquals(e.getMessage(), "Connection refused");
+        }
+
+        statusChannelClosed();
+    }
+
+    /**
+     * finish-->connect-->finish-->close
+     */
+    public void testCFII_FinishFirst_Server_Block() throws Exception {
+        // ensure
+        ensureServerOpen();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // finish
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_NotPending();
+        // connect
+        assertTrue(this.channel1.connect(localAddr1));
+        statusConnected_NotPending();
+
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+
+    }
+
+    /**
+     * finish-->connect-->finish-->close
+     */
+    public void testCFII_FinishFirst_Server_NonBlock() throws Exception {
+        // ensure
+        ensureServerOpen();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // finish
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // OK.
+        }
+        statusNotConnected_NotPending();
+        // connect
+        boolean connected = channel1.connect(localAddr1);
+        if (!connected) {
+            statusNotConnected_Pending();
+        }
+        tryFinish();
+
+        this.channel1.close();
+        statusChannelClosed();
+    }
+
+    public void testCFII_Null() throws Exception {
+        statusNotConnected_NotPending();
+        try {
+            this.channel1.connect(null);
+            fail("Should throw an IllegalArgumentException here.");
+        } catch (IllegalArgumentException e) {
+            // OK.
+        }
+    }
+
+    public void testCFII_UnsupportedType() throws Exception {
+        class SubSocketAddress extends SocketAddress {
+            private static final long serialVersionUID = 1L;
+
+            //empty
+            public SubSocketAddress() {
+                super();
+            }
+        }
+        statusNotConnected_NotPending();
+        SocketAddress newTypeAddress = new SubSocketAddress();
+        try {
+            this.channel1.connect(newTypeAddress);
+            fail("Should throw an UnsupportedAddressTypeException here.");
+        } catch (UnsupportedAddressTypeException e) {
+            // OK.
+        }
+    }
+
+    public void testCFII_Unresolved() throws IOException {
+        statusNotConnected_NotPending();
+        InetSocketAddress unresolved = new InetSocketAddress(
+                "unresolved address", 1080);
+        try {
+            this.channel1.connect(unresolved);
+            fail("Should throw an UnresolvedAddressException here.");
+        } catch (UnresolvedAddressException e) {
+            // OK.
+        }
+    }
+
+    public void testCFII_EmptyHost() throws Exception {
+        statusNotConnected_NotPending();
+        ServerSocket server = new ServerSocket(0);
+        int port = server.getLocalPort();
+        server.close();
+        try {
+            this.channel1.connect(new InetSocketAddress("", port));
+            fail("Should throw ConnectException");
+        } catch (ConnectException e) {
+            // correct
+        }
+    }
+
+    public void testCFII_CloseFirst() throws Exception {
+        this.channel1.close();
+        statusChannelClosed();
+        ensureServerOpen();
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+        try {
+            this.channel1.configureBlocking(false);
+            fail("Should throw ClosedChannelException.");
+        } catch (ClosedChannelException e) {
+            // OK.
+        }
+        statusChannelClosed();
+    }
+
+    public void testCFII_StatusAfterFinish() throws Exception {
+        // 1. close server, finish must return false, check the status
+        ensureServerClosed();
+
+        // 1.1 block mode
+        assertTrue(this.channel1.isBlocking());
+        try {
+            channel1.connect(localAddr1);
+            fail("Should throw ConnectException");
+        } catch (ConnectException e) {
+            // OK.
+        }
+        assertFalse(this.channel1.isOpen());
+
+        assertFalse(this.channel1.isOpen());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnectionPending());
+
+        // 1.2 non block mode
+        this.channel1 = SocketChannel.open();
+        this.channel1.configureBlocking(false);
+        assertFalse(this.channel1.connect(localAddr1));
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+            this.channel1.close();
+        } catch (ConnectException e) {
+            System.out.println(e.getMessage());
+        }
+
+        // 2. start server, finish usually return true, check the status
+        ensureServerOpen();
+
+        // 2.1 block mode
+        this.channel1 = SocketChannel.open();
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.connect(localAddr1));
+        assertTrue(this.channel1.finishConnect());
+        statusConnected_NotPending();
+        this.channel1.close();
+
+        // 2.2 non block mode
+        this.channel1 = SocketChannel.open();
+        this.channel1.configureBlocking(false);
+        assertFalse(this.channel1.connect(localAddr1));
+        tryFinish();
+        this.channel1.close();
+    }
+
+    private void ensureServerClosed() throws IOException {
+        if (null != this.server1) {
+            this.server1.close();
+            assertTrue(this.server1.isClosed());
+        }
+        if (null != this.server2) {
+            this.server2.close();
+            assertTrue(this.server2.isClosed());
+        }
+    }
+
+    private void ensureServerOpen() throws IOException {
+        ensureServerClosed();
+        this.server1 = new ServerSocket(localAddr1.getPort());
+        this.server2 = new ServerSocket(localAddr2.getPort());
+        assertTrue(this.server1.isBound());
+        assertTrue(this.server2.isBound());
+    }
+
+    private void connectNoServerNonBlock() throws Exception {
+        // ensure
+        ensureServerClosed();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        assertFalse(this.channel1.connect(localAddr1));
+        statusNotConnected_Pending();
+        try {
+            assertFalse(this.channel1.finishConnect());
+            statusNotConnected_Pending();
+        } catch (ConnectException e) {
+            // FIXME: assertEquals(e.getMessage(), "Connection refused");
+        }
+    }
+
+    private void connectServerNonBlock() throws Exception {
+        // ensure
+        ensureServerOpen();
+        this.channel1.configureBlocking(false);
+        statusNotConnected_NotPending();
+        // connect
+        boolean connected = channel1.connect(localAddr1);
+        if (!connected) {
+            statusNotConnected_Pending();
+        }
+        tryFinish();
+    }
+
+    private void connectServerBlock() throws Exception {
+        // ensure
+        ensureServerOpen();
+        assertTrue(this.channel1.isBlocking());
+        statusNotConnected_NotPending();
+        // connect
+        assertTrue(this.channel1.connect(localAddr1));
+        statusConnected_NotPending();
+        tryFinish();
+    }
+
+    private void statusChannelClosed() {
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertFalse(this.channel1.isOpen());
+    }
+
+    private void statusNotConnected_NotPending() {
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+    }
+
+    private void statusNotConnected_Pending() {
+        assertFalse(this.channel1.isConnected());
+        assertTrue(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+    }
+
+    private void statusConnected_NotPending() {
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+    }
+
+    private boolean tryFinish() throws IOException {
+        /*
+         * the result of finish will be asserted in multi-thread tests.
+         */
+        boolean connected = false;
+        assertTrue(this.channel1.isOpen());
+        try {
+            connected = this.channel1.finishConnect();
+        } catch (SocketException e) {
+            // Finish connection failed, probably due to reset by peer error.
+        }
+        if (connected) {
+            statusConnected_NotPending();
+        }
+        return connected;
+    }
+
+    // -------------------------------------------------------------------
+    // Original tests. Test method for CFII with real data.
+    // -------------------------------------------------------------------
+
+    /**
+     *
+     * 'SocketChannelImpl.connect(SocketAddress)'
+     */
+    public void testCFII_Data_ConnectWithServer() throws Exception {
+        ensureServerOpen();
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocate(CAPACITY_NORMAL);
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+
+        this.channel1.connect(localAddr1);
+
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+
+        this.channel1.configureBlocking(false);
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw AlreadyConnectedException");
+        } catch (AlreadyConnectedException e) {
+            // correct
+        }
+
+        assertFalse(this.channel1.isRegistered());
+        tryFinish();
+    }
+
+    /*
+     * Test method for 'SocketChannelImpl.connect(SocketAddress)'
+     */
+    public void testCFII_Data_ConnectWithServer_nonBlocking() throws Exception {
+        ensureServerOpen();
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocate(CAPACITY_NORMAL);
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        this.channel1.configureBlocking(false);
+        this.channel1.connect(localAddr1);
+
+        assertFalse(this.channel1.isBlocking());
+        boolean connected = channel1.isConnected();
+        if (!connected) {
+            assertTrue(this.channel1.isConnectionPending());
+            assertTrue(this.channel1.isOpen());
+        }
+        if (tryFinish()) {
+            assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+            assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+
+            this.channel1.configureBlocking(false);
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw AlreadyConnectedException");
+            } catch (AlreadyConnectedException e) {
+                // correct
+            }
+        }
+
+        assertFalse(this.channel1.isRegistered());
+        tryFinish();
+    }
+
+    /*
+     * Test method for 'SocketChannelImpl.finishConnect()'
+     */
+    public void testCFII_Data_FinishConnect_nonBlocking() throws IOException {
+        ensureServerOpen();
+
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocate(CAPACITY_NORMAL);
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+
+        this.channel1.configureBlocking(false);
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // correct
+        }
+        boolean connected = channel1.connect(localAddr1);
+        if (!connected) {
+            assertFalse(this.channel1.isBlocking());
+            assertFalse(this.channel1.isConnected());
+            assertTrue(this.channel1.isConnectionPending());
+            assertTrue(this.channel1.isOpen());
+        }
+        this.server1.accept();
+        if (tryFinish()) {
+            assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+            assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw AlreadyConnectedException");
+            } catch (AlreadyConnectedException e) {
+                // correct
+            }
+        }
+        assertFalse(this.channel1.isRegistered());
+        tryFinish();
+    }
+
+    public void testCFII_Data_FinishConnect_AddrSetServerStartLater()
+            throws IOException, InterruptedException {
+        ensureServerClosed();
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+        this.channel1.configureBlocking(false);
+        try {
+            SocketChannel.open(localAddr1);
+            fail("Should throw ConnectException");
+        } catch (ConnectException e) {
+            // correct
+        }
+        assertTrue(this.channel1.isOpen());
+        assertFalse(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnectionPending());
+        this.channel1.configureBlocking(true);
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // correct
+        }
+        try {
+            this.channel1.connect(localAddr2);
+            fail("Should throw ConnectException");
+        } catch (ConnectException e) {
+            // correct
+        }
+
+        assertTrue(this.channel1.isBlocking());
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+        assertFalse(this.channel1.isConnected());
+        // finish after finish OK
+        assertFalse(this.channel1.isConnectionPending());
+        this.channel1 = SocketChannel.open();
+        this.channel1.configureBlocking(false);
+        this.channel1.connect(localAddr1);
+        assertFalse(this.channel1.isConnected());
+        ensureServerOpen();
+        // cannot connect?
+        try {
+            assertFalse(this.channel1.finishConnect());
+            assertFalse(this.channel1.isBlocking());
+            assertFalse(this.channel1.isConnected());
+            assertTrue(this.channel1.isConnectionPending());
+            assertTrue(this.channel1.isOpen());
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw ConnectionPendingException");
+            } catch (ConnectionPendingException e) {
+                // correct
+            }
+            this.channel1.configureBlocking(true);
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw ConnectionPendingException");
+            } catch (ConnectionPendingException e) {
+                // correct
+            }
+            tryFinish();
+        } catch (ConnectException e) {
+            // FIXME: assertEquals(e.getMessage(), "Connection refused");
+        }
+    }
+
+    public void testCFII_Data_FinishConnect_ServerStartLater()
+            throws IOException {
+        ensureServerClosed();
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+        this.channel1.configureBlocking(true);
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // correct
+        }
+        try {
+            this.channel1.connect(localAddr1);
+            fail("Should throw ConnectException");
+        } catch (ConnectException e) {
+            // correct
+        }
+
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+        assertFalse(this.channel1.isConnected());
+        // finish after finish OK
+        assertFalse(this.channel1.isConnectionPending());
+        this.channel1 = SocketChannel.open();
+        this.channel1.configureBlocking(false);
+        this.channel1.connect(localAddr1);
+        assertFalse(this.channel1.isConnected());
+        ensureServerOpen();
+        // cannot connect?
+        try {
+            assertFalse(this.channel1.finishConnect());
+            assertFalse(this.channel1.isBlocking());
+            assertFalse(this.channel1.isConnected());
+            assertTrue(this.channel1.isConnectionPending());
+            assertTrue(this.channel1.isOpen());
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw ConnectionPendingException");
+            } catch (ConnectionPendingException e) {
+                // correct
+            }
+            this.channel1.configureBlocking(true);
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw ConnectionPendingException");
+            } catch (ConnectionPendingException e) {
+                // correct
+            }
+            tryFinish();
+        } catch (ConnectException e) {
+            // FIXME: assertEquals(e.getMessage(), "Connection refused");
+        }
+    }
+
+    public void testCFII_Data_FinishConnect_Blocking() throws IOException {
+        ensureServerOpen();
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocate(CAPACITY_NORMAL);
+        java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+        writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+        this.channel1.configureBlocking(true);
+        try {
+            this.channel1.finishConnect();
+            fail("Should throw NoConnectionPendingException");
+        } catch (NoConnectionPendingException e) {
+            // correct
+        }
+
+        this.channel1.connect(localAddr1);
+
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        if (tryFinish()) {
+            assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+            assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+
+            try {
+                this.channel1.connect(localAddr1);
+                fail("Should throw AlreadyConnectedException");
+            } catch (AlreadyConnectedException e) {
+                // correct
+            }
+        }
+        assertFalse(this.channel1.isRegistered());
+        tryFinish();
+    }
+
+    /**
+     * Regression test for Harmony-1947.
+     */
+    public void test_finishConnect() throws Exception {
+        SocketAddress address = new InetSocketAddress("localhost", 0);
+
+        ServerSocketChannel theServerChannel = ServerSocketChannel.open();
+        ServerSocket serversocket = theServerChannel.socket();
+        serversocket.setReuseAddress(true);
+        // Bind the socket
+        serversocket.bind(address);
+
+        boolean doneNonBlockingConnect = false;
+        // Loop so that we make sure we're definitely testing finishConnect()
+        while (!doneNonBlockingConnect) {
+            channel1 = SocketChannel.open();
+
+            // Set the SocketChannel to non-blocking so that connect(..) does
+            // not block
+            channel1.configureBlocking(false);
+            boolean connected = channel1.connect(new InetSocketAddress("localhost",serversocket.getLocalPort()));
+            if (!connected) {
+                // Now set the SocketChannel back to blocking so that
+                // finishConnect() blocks.
+                channel1.configureBlocking(true);
+                doneNonBlockingConnect = channel1.finishConnect();
+            }
+            if (doneNonBlockingConnect) {
+                tryFinish();
+            }
+            channel1.close();
+        }
+        if (!serversocket.isClosed()) {
+            serversocket.close();
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // End of original tests. Test method for CFII with real data.
+    // -------------------------------------------------------------------
+
+    /**
+     * @tests java.nio.channels.SocketChannel#read(ByteBuffer)
+     */
+    public void test_readLjava_nio_ByteBuffer_Blocking() throws IOException {
+        // initialize write content
+        byte[] writeContent = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < writeContent.length; i++) {
+            writeContent[i] = (byte) i;
+        }
+        // establish connection
+        channel1.connect(localAddr1);
+        Socket acceptedSocket = server1.accept();
+
+        // use OutputStream.write to send CAPACITY_NORMAL bytes data
+        OutputStream out = acceptedSocket.getOutputStream();
+        out.write(writeContent);
+        // use close to guarantee all data is sent
+        acceptedSocket.close();
+
+        ByteBuffer readContent = ByteBuffer.allocate(CAPACITY_NORMAL + 1);
+        int totalCount = 0;
+        int count = 0;
+        long startTime = System.currentTimeMillis();
+        // use SocketChannel.read to read data
+        while (totalCount <= CAPACITY_NORMAL) {
+            count = channel1.read(readContent);
+            if (EOF == count) {
+                break;
+            }
+            totalCount += count;
+            // if the channel could not finish reading in TIMEOUT ms, the
+            // test fails. It is used to guarantee the test never hangs even
+            // if there are bugs of SocketChannel implementation. For
+            // blocking read, it possibly returns 0 in some cases.
+            assertTimeout(startTime, TIMEOUT);
+        }
+        assertEquals(CAPACITY_NORMAL, totalCount);
+        readContent.flip();
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            assertEquals(writeContent[i], readContent.get());
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#read(ByteBuffer)
+     */
+    public void test_readLjava_nio_ByteBuffer_Nonblocking() throws IOException {
+        // initialize write content
+        byte[] writeContent = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < writeContent.length; i++) {
+            writeContent[i] = (byte) i;
+        }
+
+        // establish connection
+        channel1.connect(localAddr1);
+        Socket acceptedSocket = server1.accept();
+        // use OutputStream.write to write CAPACITY_NORMAL bytes data.
+        OutputStream out = acceptedSocket.getOutputStream();
+        out.write(writeContent);
+        // use close to guarantee all data is sent
+        acceptedSocket.close();
+
+        channel1.configureBlocking(false);
+        ByteBuffer readContent = ByteBuffer.allocate(CAPACITY_NORMAL + 1);
+        int totalCount = 0;
+        int count = 0;
+        long startTime = System.currentTimeMillis();
+        // use SocketChannel.read to read data
+        while (totalCount <= CAPACITY_NORMAL) {
+            count = channel1.read(readContent);
+            if (EOF == count) {
+                break;
+            }
+            totalCount += count;
+            // if the channel could not finish reading in TIMEOUT ms, the
+            // test fails. It is used to guarantee the test never hangs even
+            // if there are bugs of SocketChannel implementation.
+            assertTimeout(startTime, TIMEOUT);
+        }
+
+        // assert read content
+        assertEquals(CAPACITY_NORMAL, totalCount);
+        assertEquals(CAPACITY_NORMAL, readContent.position());
+        readContent.flip();
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            assertEquals(writeContent[i], readContent.get());
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer)
+     */
+    public void test_writeLjava_nio_ByteBuffer_Blocking() throws IOException {
+        // initialize write content
+        ByteBuffer writeContent = ByteBuffer.allocate(CAPACITY_NORMAL);
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            writeContent.put((byte) i);
+        }
+        writeContent.flip();
+        // establish connection
+        channel1.connect(localAddr1);
+        Socket acceptedSocket = server1.accept();
+
+        // use SocketChannel.write(ByteBuffer) to write CAPACITY_NORMAL bytes
+        // data
+        int writtenCount = channel1.write(writeContent);
+        // assert written count and ByteBuffer position
+        assertEquals(CAPACITY_NORMAL, writtenCount);
+        assertEquals(CAPACITY_NORMAL, writeContent.position());
+        // use close to guarantee all data is sent
+        channel1.close();
+
+        InputStream in = acceptedSocket.getInputStream();
+        int totalCount = 0;
+        int count = 0;
+        byte[] readContent = new byte[CAPACITY_NORMAL + 1];
+        // if the channel could not finish reading in TIMEOUT ms, the test
+        // fails. It is used to guarantee the test never hangs even if there
+        // are bugs of SocketChannel implementation.
+        acceptedSocket.setSoTimeout(TIMEOUT);
+
+        // use InputStream.read to read data.
+        while (totalCount <= CAPACITY_NORMAL) {
+            count = in.read(readContent, totalCount, readContent.length
+                    - totalCount);
+            if (EOF == count) {
+                break;
+            }
+            totalCount += count;
+        }
+
+        // assert read content
+        assertEquals(CAPACITY_NORMAL, totalCount);
+        writeContent.flip();
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            assertEquals(writeContent.get(), readContent[i]);
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer)
+     */
+    public void test_writeLjava_nio_ByteBuffer_NonBlocking() throws Exception {
+        // initialize write content
+        ByteBuffer writeContent = ByteBuffer.allocate(CAPACITY_NORMAL);
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            writeContent.put((byte) i);
+        }
+        writeContent.flip();
+
+        // establish connection
+        channel1.connect(localAddr1);
+        Socket acceptedSocket = server1.accept();
+
+        channel1.configureBlocking(false);
+        int writtenTotalCount = 0;
+        int writtenCount = 0;
+        long startTime = System.currentTimeMillis();
+        // use SocketChannel.write(ByteBuffer) to write CAPACITY_NORMAL bytes
+        while (writtenTotalCount < CAPACITY_NORMAL) {
+            writtenCount = channel1.write(writeContent);
+            writtenTotalCount += writtenCount;
+            // if the channel could not finish writing in TIMEOUT ms, the
+            // test fails. It is used to guarantee the test never hangs even
+            // if there are bugs of SocketChannel implementation.
+            assertTimeout(startTime, TIMEOUT);
+        }
+        // assert written count and ByteBuffer position
+        assertEquals(CAPACITY_NORMAL, writtenTotalCount);
+        assertEquals(CAPACITY_NORMAL, writeContent.position());
+        // use close to guarantee all data is sent
+        channel1.close();
+
+        InputStream in = acceptedSocket.getInputStream();
+        byte[] readContent = new byte[CAPACITY_NORMAL + 1];
+        int totalCount = 0;
+        int count = 0;
+        // if the channel could not finish reading in TIMEOUT ms, the test
+        // fails. It is used to guarantee the test never hangs even if there
+        // are bugs of SocketChannel implementation.
+        acceptedSocket.setSoTimeout(TIMEOUT);
+        // use InputStream.read to read data.
+        while (totalCount <= CAPACITY_NORMAL) {
+            count = in.read(readContent, totalCount, readContent.length
+                    - totalCount);
+            if (EOF == count) {
+                break;
+            }
+            totalCount += count;
+        }
+        // assert read content
+        assertEquals(CAPACITY_NORMAL, totalCount);
+        writeContent.flip();
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            assertEquals(writeContent.get(), readContent[i]);
+        }
+    }
+
+    /*
+     * Fails if the difference between current time and start time is greater
+     * than timeout.
+     */
+    private void assertTimeout(long startTime, long timeout) {
+        long currentTime = System.currentTimeMillis();
+        if ((currentTime - startTime) > timeout) {
+            fail("Timeout");
+        }
+    }
+
+    // -------------------------------------------------
+    // Test for read/write but no real data expressed
+    // -------------------------------------------------
+
+    public void testReadByteBuffer() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer readBuf = java.nio.ByteBuffer
+                .allocate(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            channel1.read(readBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        boolean connected = this.channel1.connect(localAddr1);
+        if (!connected) {
+            assertFalse(this.channel1.isBlocking());
+            assertTrue(this.channel1.isConnectionPending());
+            assertFalse(this.channel1.isConnected());
+        }
+        if (tryFinish()) {
+            assertEquals(0, this.channel1.read(readBuf));
+        }
+
+        this.channel1.close();
+        try {
+            channel1.read(readBuf);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testReadByteBuffer_Direct() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer readBuf = java.nio.ByteBuffer
+                .allocateDirect(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            channel1.read(readBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        boolean connected = this.channel1.connect(localAddr1);
+        if (!connected) {
+            assertFalse(this.channel1.isBlocking());
+            assertTrue(this.channel1.isConnectionPending());
+            assertFalse(this.channel1.isConnected());
+        }
+        if (tryFinish()) {
+            assertEquals(0, this.channel1.read(readBuf));
+        }
+
+        this.channel1.close();
+        try {
+            channel1.read(readBuf);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testReadByteBuffer_Direct2() throws IOException {
+        byte[] request = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+        ByteBuffer buffer = ByteBuffer.allocateDirect(128);
+
+        ServerSocketChannel server = ServerSocketChannel.open();
+        server.socket().bind(
+                new InetSocketAddress(InetAddress.getLocalHost(), 0), 5);
+        Socket client = new Socket(InetAddress.getLocalHost(), server.socket()
+                .getLocalPort());
+        client.setTcpNoDelay(false);
+        Socket worker = server.socket().accept();
+        SocketChannel workerChannel = worker.getChannel();
+
+        OutputStream out = client.getOutputStream();
+        out.write(request);
+        out.close();
+
+        buffer.limit(5);
+        int bytesRead = workerChannel.read(buffer);
+        assertEquals(5, bytesRead);
+        assertEquals(5, buffer.position());
+
+        buffer.limit(request.length);
+        bytesRead = workerChannel.read(buffer);
+        assertEquals(6, bytesRead);
+
+        buffer.flip();
+        assertEquals(request.length, buffer.limit());
+
+        assertEquals(ByteBuffer.wrap(request), buffer);
+
+        client.close();
+        worker.close();
+        server.close();
+    }
+
+    public void testReadByteBuffer_BufNull() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer readBuf = java.nio.ByteBuffer.allocate(0);
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            channel1.read((java.nio.ByteBuffer) null);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        if (tryFinish()) {
+            try {
+                this.channel1.read((java.nio.ByteBuffer) null);
+                fail("Should throw NPE");
+            } catch (NullPointerException e) {
+                // correct
+            }
+            assertEquals(0, this.channel1.read(readBuf));
+        }
+        this.server1.close();
+        try {
+            channel1.read((java.nio.ByteBuffer) null);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.read(ByteBuffer[], int, int)'
+     */
+    public void testReadByteBufferArrayIntInt() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+        readBuf[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+        readBuf[1] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            channel1.read(readBuf, 0, 1);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        boolean connected = this.channel1.connect(localAddr1);
+        if (!connected) {
+            assertFalse(this.channel1.isBlocking());
+            assertTrue(this.channel1.isConnectionPending());
+            assertFalse(this.channel1.isConnected());
+        }
+        if (tryFinish()) {
+            assertEquals(0, this.channel1.read(readBuf, 0, 1));
+            assertEquals(0, this.channel1.read(readBuf, 0, 2));
+        }
+
+        this.channel1.close();
+        try {
+            channel1.read(readBuf, 0, 1);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.read(ByteBuffer[], int, int)'
+     */
+    public void testReadByteBufferArrayIntInt_Direct() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+        readBuf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        readBuf[1] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            channel1.read(readBuf, 0, 1);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        boolean connected = this.channel1.connect(localAddr1);
+        if (!connected) {
+            assertFalse(this.channel1.isBlocking());
+            assertTrue(this.channel1.isConnectionPending());
+            assertFalse(this.channel1.isConnected());
+        }
+        if (tryFinish()) {
+            assertEquals(0, this.channel1.read(readBuf, 0, 1));
+            assertEquals(0, this.channel1.read(readBuf, 0, 2));
+        }
+
+        this.channel1.close();
+        try {
+            channel1.read(readBuf, 0, 1);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testReadByteBufferArrayIntInt_BufNull() throws Exception {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+        readBuf[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        // note: blocking-mode will make the read process endless!
+        this.channel1.configureBlocking(false);
+        try {
+            channel1.read(null, 0, 0);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        if (tryFinish()) {
+
+            try {
+                channel1.read(null, 0, 0);
+                fail("Should throw NPE");
+            } catch (NullPointerException e) {
+                // correct
+            }
+            try {
+                channel1.read(readBuf, 0, 2);
+                fail("Should throw NPE");
+            } catch (NullPointerException e) {
+                // correct
+            }
+
+            assertEquals(0, this.channel1.read(readBuf, 0, 1));
+        }
+        this.channel1.close();
+        try {
+            channel1.read(null, 0, 1);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBuffer() throws IOException {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocate(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        try {
+            channel1.write(writeBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+
+        this.channel1.close();
+        try {
+            channel1.write(writeBuf);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBuffer_Direct() throws IOException {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+                .allocateDirect(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        try {
+            channel1.write(writeBuf);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+
+        this.channel1.close();
+        try {
+            channel1.write(writeBuf);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBuffer_BufNull() throws IOException {
+        assertTrue(this.server1.isBound());
+        java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer.allocate(0);
+        this.channel1.connect(localAddr1);
+        assertEquals(this.channel1.write(writeBuf), 0);
+        try {
+            this.channel1.write((java.nio.ByteBuffer) null);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.write(ByteBuffer[], int, int)'
+     */
+    public void testWriteByteBufferArrayIntInt() throws IOException {
+        java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[2];
+        writeBuf[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+        writeBuf[1] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        try {
+            channel1.write(writeBuf, 0, 1);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 1));
+        // still writes the same size as above
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 2));
+        writeBuf[0].flip();
+        writeBuf[1].flip();
+        assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+        this.channel1.close();
+        try {
+            channel1.write(writeBuf);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    /*
+     * SocketChannelImpl.write(ByteBuffer[], int, int)'
+     */
+    public void testWriteByteBufferArrayIntInt_Direct() throws IOException {
+        java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[2];
+        writeBuf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        writeBuf[1] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+        assertFalse(this.channel1.isRegistered());
+        assertTrue(this.channel1.isBlocking());
+        assertFalse(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        try {
+            channel1.write(writeBuf, 0, 1);
+            fail("Should throw NotYetConnectedException");
+        } catch (NotYetConnectedException e) {
+            // correct
+        }
+        this.channel1.connect(localAddr1);
+        assertTrue(this.channel1.isBlocking());
+        assertTrue(this.channel1.isConnected());
+        assertFalse(this.channel1.isConnectionPending());
+        assertTrue(this.channel1.isOpen());
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 1));
+        // still writes the same size as above
+        assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 2));
+        writeBuf[0].flip();
+        writeBuf[1].flip();
+        assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+        this.channel1.close();
+        try {
+            channel1.write(writeBuf);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBufferArrayIntInt_BufNull() throws IOException {
+        java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[0];
+
+        this.channel1.connect(localAddr1);
+        try {
+            this.channel1.write(null, 0, 1);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        assertEquals(0, this.channel1.write(writeBuf, 0, 0));
+        try {
+            this.channel1.write(writeBuf, 0, 1);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        writeBuf = new java.nio.ByteBuffer[1];
+        try {
+            this.channel1.write(writeBuf, 0, 1);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+        try {
+            this.channel1.write(writeBuf, 0, 2);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // correct
+        }
+        this.server1.close();
+        try {
+            channel1.read(null, 0, 1);
+            fail("Should throw NPE");
+        } catch (NullPointerException e) {
+            // correct
+        }
+    }
+
+    public void testWriteByteBufferArrayIntInt_SizeError() throws IOException {
+        java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[1];
+        this.channel1.connect(localAddr1);
+        assertEquals(0, this.channel1.write(buf, 0, 0));
+        try {
+            this.channel1.write(buf, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            this.channel1.write(buf, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            this.channel1.write(buf, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            this.channel1.write(buf, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            this.channel1.write(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        this.server1.close();
+    }
+
+    public void testReadByteBufferArrayIntInt_SizeError() throws IOException {
+        java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[1];
+        this.channel1.connect(localAddr1);
+        assertEquals(0, this.channel1.read(buf, 0, 0));
+        try {
+            this.channel1.read(buf, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            this.channel1.read(buf, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            this.channel1.read(buf, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            this.channel1.read(buf, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            this.channel1.read(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        this.server1.close();
+    }
+
+    /*
+     * ==========================================================================
+     * Tests for read/write real data
+     * ==========================================================================
+     */
+
+
+    /**
+     * @tests java.nio.channels.SocketChannel#read(ByteBuffer[])
+     */
+    public void test_read$LByteBuffer() throws IOException {
+        MockSocketChannel sc = new MockSocketChannel(null);
+        ByteBuffer [] byteBufferArray = { ByteBuffer.allocate(1), ByteBuffer.allocate(1)};
+        // Verify that calling read(ByteBuffer[]) leads to the method
+        // read(ByteBuffer[], int, int) being called with a 0 for the
+        // second parameter and targets.length as the third parameter.
+        sc.read(byteBufferArray);
+        assertTrue(sc.isReadCalled);
+    }
+    /**
+     * @tests java.nio.channels.SocketChannel#read(ByteBuffer[],int,int)
+     */
+    public void test_read$LByteBufferII_blocking() throws Exception {
+        assert_read$LByteBuffer(true);
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#read(ByteBuffer[],int,int)
+     */
+    public void test_read$LByteBufferII_nonblocking() throws Exception {
+        assert_read$LByteBuffer(false);
+    }
+
+    private void assert_read$LByteBuffer(boolean isBlocking) throws IOException {
+        // initialize write content
+        byte[] writeContent = new byte[CAPACITY_NORMAL * 2];
+        for (int i = 0; i < CAPACITY_NORMAL * 2; i++) {
+            writeContent[i] = (byte) i;
+        }
+        ByteBuffer[] readContents = new ByteBuffer[2];
+        readContents[0] = ByteBuffer.allocate(CAPACITY_NORMAL);
+        readContents[1] = ByteBuffer.allocate(CAPACITY_NORMAL + 1);
+        // establish connection
+        channel1.connect(localAddr1);
+        Socket acceptedSocket = server1.accept();
+        // use OutputStream.write to send CAPACITY_NORMAL * 2 bytes data
+        OutputStream out = acceptedSocket.getOutputStream();
+        out.write(writeContent);
+        // use close to guarantee all data is sent
+        acceptedSocket.close();
+        // configure block/nonblock mode
+        channel1.configureBlocking(isBlocking);
+        long startTime = System.currentTimeMillis();
+        long totalRead = 0;
+        long countRead = 0;
+
+        while (totalRead <= CAPACITY_NORMAL * 2) {
+            countRead = channel1.read(readContents, 0, 2);
+            if (0 == countRead && !readContents[1].hasRemaining()) {
+                // read returns 0 because readContents is full
+                break;
+            }
+            if (EOF == countRead) {
+                break;
+            }
+            totalRead += countRead;
+            // if the channel could not finish reading in TIMEOUT ms, the
+            // test fails. It is used to guarantee the test never hangs even
+            // if there are bugs of SocketChannel implementation. For
+            // blocking read, it possibly returns 0 in some cases.
+            assertTimeout(startTime, TIMEOUT);
+        }
+
+        // assert total bytes read and the position of ByteBuffers
+        assertEquals(CAPACITY_NORMAL * 2, totalRead);
+        assertEquals(CAPACITY_NORMAL, readContents[0].position());
+        assertEquals(CAPACITY_NORMAL, readContents[1].position());
+        // assert read content
+        readContents[0].flip();
+        readContents[1].flip();
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            assertEquals(writeContent[i], readContents[0].get());
+        }
+        for (int i = CAPACITY_NORMAL; i < CAPACITY_NORMAL * 2; i++) {
+            assertEquals(writeContent[i], readContents[1].get());
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[],int,int)
+     */
+    public void test_write$LByteBufferII_blocking() throws Exception {
+        assert_write$LByteBuffer(true);
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[],int,int)
+     */
+    public void test_write$LByteBufferII_nonblocking()
+            throws Exception {
+        assert_write$LByteBuffer(false);
+    }
+
+    private void assert_write$LByteBuffer(boolean isBlocking)
+            throws IOException {
+        // initialize write contents
+        ByteBuffer writeContents[] = new ByteBuffer[2];
+        writeContents[0] = ByteBuffer.allocate(CAPACITY_NORMAL);
+        writeContents[1] = ByteBuffer.allocate(CAPACITY_NORMAL);
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            writeContents[0].put((byte) i);
+        }
+        for (int i = CAPACITY_NORMAL; i < CAPACITY_NORMAL * 2; i++) {
+            writeContents[1].put((byte) i);
+        }
+        writeContents[0].flip();
+        writeContents[1].flip();
+        // establish connection
+        channel1.connect(localAddr1);
+        Socket acceptedSocket = server1.accept();
+        // set blocking/nonblocking mode
+        channel1.configureBlocking(isBlocking);
+
+        assertEquals(CAPACITY_NORMAL, channel1.write(writeContents, 0, 1));
+        assertEquals(CAPACITY_NORMAL, channel1.write(writeContents, 1, 1));
+
+        // assert written count and ByteBuffer position
+        assertEquals(CAPACITY_NORMAL, writeContents[0].position());
+        assertEquals(CAPACITY_NORMAL, writeContents[1].position());
+        // use close to guarantee all data is sent
+        channel1.close();
+        InputStream in = acceptedSocket.getInputStream();
+        byte[] readContent = new byte[CAPACITY_NORMAL * 2 + 1];
+        int totalCount = 0;
+        int count = 0;
+        // if the channel could not finish reading in TIMEOUT ms, the test
+        // fails. It is used to guarantee the test never hangs even if there
+        // are bugs of SocketChannel implementation.
+        acceptedSocket.setSoTimeout(TIMEOUT);
+        // use InputStream.read to read data.
+        while (totalCount <= CAPACITY_NORMAL) {
+            count = in.read(readContent, totalCount, readContent.length
+                    - totalCount);
+            if (EOF == count) {
+                break;
+            }
+            totalCount += count;
+        }
+        // assert read content
+        assertEquals(CAPACITY_NORMAL * 2, totalCount);
+        writeContents[0].flip();
+        writeContents[1].flip();
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            assertEquals(writeContents[0].get(), readContent[i]);
+        }
+        for (int i = CAPACITY_NORMAL; i < CAPACITY_NORMAL * 2; i++) {
+            assertEquals(writeContents[1].get(), readContent[i]);
+        }
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+     */
+    public void test_write$LByteBuffer() throws IOException {
+        MockSocketChannel sc = new MockSocketChannel(null);
+        ByteBuffer [] byteBufferArray = { ByteBuffer.allocate(1), ByteBuffer.allocate(1)};
+        // Verify that calling write(ByteBuffer[]) leads to the method
+        // write(ByteBuffer[], int, int) being called with a 0 for the
+        // second parameter and sources.length as the third parameter.
+        sc.write(byteBufferArray);
+        assertTrue(sc.isWriteCalled);
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+     */
+    public void test_writev() throws Exception {
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(localAddr2);
+        SocketChannel sc = SocketChannel.open();
+        sc.connect(localAddr2);
+        SocketChannel sock = ssc.accept();
+        ByteBuffer[] buf = { ByteBuffer.allocate(10), ByteBuffer.allocateDirect(20) };
+
+        while (buf[0].remaining() != 0 && buf[1].remaining() !=0) {
+            assertTrue(sc.write(buf, 0, 2) >= 0);
+        }
+
+        ByteBuffer target = ByteBuffer.allocate(30);
+
+        while (target.remaining() != 0) {
+            assertTrue(sock.read(target) >=0);
+        }
+
+        ssc.close();
+        sc.close();
+        sock.close();
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+     */
+    public void test_writev2() throws Exception {
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.configureBlocking(false);
+        ssc.socket().bind(null);
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        boolean connected = sc.connect(ssc.socket().getLocalSocketAddress());
+        SocketChannel sock = ssc.accept();
+        if (!connected) {
+            sc.finishConnect();
+        }
+
+        ByteBuffer buf1 = ByteBuffer.allocate(10);
+        sc.socket().setSendBufferSize(512);
+        int bufSize = sc.socket().getSendBufferSize();
+        ByteBuffer buf2 = ByteBuffer.allocate(bufSize * 10);
+
+        ByteBuffer[] sent = new ByteBuffer[2];
+        sent[0] = buf1;
+        sent[1] = buf2;
+
+        long whole = buf1.remaining() + buf2.remaining();
+
+        long write = sc.write(sent);
+        ssc.close();
+        sc.close();
+        sock.close();
+
+        assertTrue(whole == (write + buf1.remaining() + buf2.remaining()));
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+     *
+     * In non-blocking mode, the native system call will return EAGAIN/EWOULDBLOCK error
+     * code on Linux/Unix and return WSATRY_AGAIN/WSAEWOULDBLOCK error code on Windows.
+     * These error code means try again but not fatal error, so we should not throw exception.
+     */
+    public void test_write$NonBlockingException() throws Exception {
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.configureBlocking(false);
+        ssc.socket().bind(null);
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        boolean connected = sc.connect(ssc.socket().getLocalSocketAddress());
+        SocketChannel sock = ssc.accept();
+        if (!connected) {
+            sc.finishConnect();
+        }
+
+        try {
+            for (int i = 0; i < 100; i++) {
+                ByteBuffer buf1 = ByteBuffer.allocate(10);
+                sc.socket().setSendBufferSize(512);
+                int bufSize = sc.socket().getSendBufferSize();
+                ByteBuffer buf2 = ByteBuffer.allocate(bufSize * 10);
+
+                ByteBuffer[] sent = new ByteBuffer[2];
+                sent[0] = buf1;
+                sent[1] = buf2;
+
+                sc.write(sent);
+            }
+        } finally {
+            ssc.close();
+            sc.close();
+            sock.close();
+        }
+
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+     */
+    public void test_write$LByteBuffer2() throws IOException {
+        // Set-up
+        ServerSocketChannel server = ServerSocketChannel.open();
+        server.socket().bind(null);
+        SocketChannel client = SocketChannel.open();
+        client.connect(server.socket().getLocalSocketAddress());
+        SocketChannel worker = server.accept();
+
+        // Test overlapping buffers
+        byte[] data = "Hello world!".getBytes("UTF-8");
+        ByteBuffer[] buffers = new ByteBuffer[3];
+        buffers[0] = ByteBuffer.wrap(data, 0, 6);
+        buffers[1] = ByteBuffer.wrap(data, 6, data.length - 6);
+        buffers[2] = ByteBuffer.wrap(data);
+
+        // Write them out, read what we wrote and check it
+        client.write(buffers);
+        client.close();
+        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
+        while (EOF != worker.read(readBuffer)) {};
+        readBuffer.flip();
+        Buffer expected = ByteBuffer.allocate(1024).put(data).put(data).flip();
+        assertEquals(expected, readBuffer);
+
+        // Tidy-up
+        worker.close();
+        server.close();
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+     */
+    public void test_write$LByteBuffer_buffers() throws IOException {
+        // Set-up
+        ServerSocketChannel server = ServerSocketChannel.open();
+        server.socket().bind(null);
+        SocketChannel client = SocketChannel.open();
+        client.connect(server.socket().getLocalSocketAddress());
+        SocketChannel worker = server.accept();
+
+        // A variety of buffer types to write
+        byte[] data = "Hello world!".getBytes("UTF-8");
+        ByteBuffer[] buffers = new ByteBuffer[3];
+        buffers[0] = ByteBuffer.wrap(data, 0, 2);
+        assertFalse(buffers[0].isDirect());
+        assertTrue(buffers[0].hasArray());
+
+        buffers[1] = ByteBuffer.wrap(data, 2, 4).asReadOnlyBuffer();
+        assertFalse(buffers[1].isDirect());
+        assertFalse(buffers[1].hasArray());
+
+        buffers[2] = ByteBuffer.allocateDirect(42);
+        buffers[2].put(data, 6, data.length - 6);
+        buffers[2].flip();
+        assertTrue(buffers[2].isDirect());
+        // Android's direct buffers do have a backing array.
+        assertTrue(buffers[2].hasArray());
+
+        // Write them out, read what we wrote and check it
+        client.write(buffers);
+        client.close();
+        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
+        while (EOF != worker.read(readBuffer)) {};
+        readBuffer.flip();
+        assertEquals(ByteBuffer.wrap(data), readBuffer);
+
+        // Tidy-up
+        worker.close();
+        server.close();
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+     */
+    public void test_write$LByteBuffer_writes() throws IOException {
+        // Set-up
+        ServerSocketChannel server = ServerSocketChannel.open();
+        server.socket().bind(null);
+        SocketChannel client = SocketChannel.open();
+        client.connect(server.socket().getLocalSocketAddress());
+        SocketChannel worker = server.accept();
+
+        // Data to write
+        byte[] data = "Hello world!".getBytes("UTF-8");
+        ByteBuffer[] buffers = new ByteBuffer[3];
+        buffers[0] = ByteBuffer.wrap(data, 0, 6);
+        buffers[1] = ByteBuffer.wrap("world!".getBytes("UTF-8"));
+        buffers[2] = buffers[0];
+        assertTrue(buffers[0].hasArray());
+
+        // Test a sequence of write calls
+        client.write(buffers, 0, 0); // write nothing
+        client.write(buffers, 1, 0); // write nothing
+        client.write(buffers, 0, 1); // write "Hello "
+        assertEquals("Failed to drain buffer 0", 0, buffers[0].remaining());
+        assertEquals("Shouldn't touch buffer 1", buffers[1].limit(), buffers[1]
+                .remaining());
+        client.write(buffers, 0, 2); // writes "world!"
+        assertEquals("Failed to drain buffer 1", 0, buffers[1].remaining());
+        client.write(buffers, 0, 3); // write nothing
+        client.close();
+
+        // Read what we wrote and check it
+        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
+        while (EOF != worker.read(readBuffer)) {};
+        readBuffer.flip();
+        assertEquals(ByteBuffer.wrap(data), readBuffer);
+
+        // Tidy-up
+        worker.close();
+        server.close();
+    }
+
+    /**
+     * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+     */
+    public void test_write$LByteBuffer_invalid() throws IOException {
+        // Set-up
+        ServerSocketChannel server = ServerSocketChannel.open();
+        server.socket().bind(null);
+
+        SocketChannel client = SocketChannel.open();
+        client.connect(server.socket().getLocalSocketAddress());
+
+        SocketChannel worker = server.accept();
+
+        // Do some stuff
+        try {
+            client.write((ByteBuffer[]) null);
+            fail("Should throw a NPE");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            client.write((ByteBuffer[]) null, 0, 0);
+            fail("Should throw a NPE");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            client.write((ByteBuffer[]) null, 1, 0);
+            fail("Should throw a NPE");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            client.write((ByteBuffer[]) null, 0, 1);
+            fail("Should throw a NPE");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            client.write((ByteBuffer[]) null, 1, 1);
+            fail("Should throw a NPE");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        ByteBuffer[] buffers = new ByteBuffer[1];
+        buffers[0] = ByteBuffer.wrap("Hello ".getBytes("UTF-8"));
+
+        try {
+            client.write(buffers, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            client.write(buffers, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            client.write(buffers, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            client.write(buffers, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            client.write(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        // Tidy-up
+        worker.close();
+        client.close();
+        server.close();
+    }
+
+    public void testSocket_configureblocking() throws IOException {
+        byte[] serverWBuf = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < serverWBuf.length; i++) {
+            serverWBuf[i] = (byte) i;
+        }
+        java.nio.ByteBuffer buf = java.nio.ByteBuffer
+                .allocate(CAPACITY_NORMAL + 1);
+        channel1.connect(localAddr1);
+        server1.accept();
+        Socket sock = this.channel1.socket();
+        channel1.configureBlocking(false);
+        assertFalse(channel1.isBlocking());
+        OutputStream channelSocketOut = sock.getOutputStream();
+        try {
+            // write operation is not allowed in non-blocking mode
+            channelSocketOut.write(buf.array());
+            fail("Non-Blocking mode should cause IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // correct
+        }
+        channel1.configureBlocking(true);
+        assertTrue(channel1.isBlocking());
+        // write operation is allowed in blocking mode
+        channelSocketOut.write(buf.array());
+    }
+
+    /**
+     * @tests SocketChannel#read(ByteBuffer[], int, int) when remote server
+     *        closed
+     */
+    public void test_socketChannel_read_ByteBufferII_remoteClosed()
+            throws Exception {
+        // regression 1 for HARMONY-549
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(localAddr2);
+        SocketChannel sc = SocketChannel.open();
+        sc.connect(localAddr2);
+        ssc.accept().close();
+        ByteBuffer[] buf = { ByteBuffer.allocate(10) };
+        assertEquals(-1, sc.read(buf, 0, 1));
+        ssc.close();
+        sc.close();
+    }
+
+    /**
+     * @tests SocketChannel#write(ByteBuffer[], int, int)
+     */
+    public void test_socketChannel_write_ByteBufferII() throws Exception {
+        // regression 2 for HARMONY-549
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(localAddr2);
+        SocketChannel sc = SocketChannel.open();
+        sc.connect(localAddr2);
+        SocketChannel sock = ssc.accept();
+        ByteBuffer[] buf = { ByteBuffer.allocate(10), null };
+        try {
+            sc.write(buf, 0, 2);
+            fail("should throw NPE");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        ssc.close();
+        sc.close();
+        ByteBuffer target = ByteBuffer.allocate(10);
+        assertEquals(-1, sock.read(target));
+    }
+
+    /**
+     * @tests SocketChannel#read(ByteBuffer[], int, int) with a null ByteBuffer
+     */
+    public void test_socketChannel_read_ByteBufferII_bufNULL() throws Exception {
+        // regression 3 for HARMONY-549
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(localAddr2);
+        SocketChannel sc = SocketChannel.open();
+        sc.connect(localAddr2);
+        ssc.accept();
+        ByteBuffer[] buf = new ByteBuffer[2];
+        buf[0] = ByteBuffer.allocate(1);
+        // let buf[1] be null
+        try {
+            sc.read(buf, 0, 2);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        ssc.close();
+        sc.close();
+    }
+
+    /**
+     * @tests SocketChannel#write(ByteBuffer) after close
+     */
+    public void test_socketChannel_write_close() throws Exception {
+        // regression 4 for HARMONY-549
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(localAddr2);
+        SocketChannel sc = SocketChannel.open();
+        sc.connect(localAddr2);
+        SocketChannel sock = ssc.accept();
+        ByteBuffer buf = null;
+        ssc.close();
+        sc.close();
+        try {
+            sc.write(buf);
+            fail("should throw NPE");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        sock.close();
+    }
+
+    /**
+     * @tests SocketChannel#write(ByteBuffer) if position is not zero
+     */
+    public void test_socketChannel_write_ByteBuffer_posNotZero()
+            throws Exception {
+        // regression 5 for HARMONY-549
+        final String testStr = "Hello World";
+        ByteBuffer readBuf = ByteBuffer.allocate(11);
+        ByteBuffer buf = ByteBuffer.wrap(testStr.getBytes());
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(localAddr2);
+        SocketChannel sc = SocketChannel.open();
+        sc.connect(localAddr2);
+        buf.position(2);
+        ssc.accept().write(buf);
+        assertEquals(9, sc.read(readBuf));
+        buf.flip();
+        readBuf.flip();
+        byte[] read = new byte[9];
+        byte[] write = new byte[11];
+        buf.get(write);
+        readBuf.get(read);
+        for (int i = 0; i < 9; i++) {
+            assertEquals(read[i], write[i + 2]);
+        }
+    }
+
+    /**
+     * @tests SocketChannelImpl#read(ByteBuffer[])
+     */
+    public void test_read_$ByteBuffer_Blocking() throws IOException {
+        // regression test for Harmony-728
+        byte[] data = new byte[CAPACITY_NORMAL];
+        for (int i = 0; i < CAPACITY_NORMAL; i++) {
+            data[i] = (byte) i;
+        }
+        ByteBuffer[] buf = new ByteBuffer[2];
+        buf[0] = ByteBuffer.allocate(CAPACITY_NORMAL);
+        buf[1] = ByteBuffer.allocate(CAPACITY_NORMAL);
+        channel1.connect(localAddr1);
+        Socket socket = null;
+        try {
+            socket = server1.accept();
+            OutputStream out = socket.getOutputStream();
+            out.write(data);
+            // should not block here
+            channel1.read(buf);
+        } finally {
+            if (null != socket) {
+                socket.close();
+            }
+        }
+    }
+
+    public void test_socket_getOutputStream_nonBlocking_read_Exception() throws IOException {
+        byte[] buf = new byte[1];
+        channel1.connect(this.localAddr1);
+        InputStream is = channel1.socket().getInputStream();
+        channel1.configureBlocking(false);
+        try {
+            is.read();
+            fail();
+        } catch (IllegalBlockingModeException expected) {
+        }
+        try {
+            is.read(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            is.read(buf, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        is.close();
+
+        try {
+            is.read();
+            fail();
+        } catch (IllegalBlockingModeException expected) {
+        }
+        try {
+            is.read(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            is.read(buf, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void test_socket_getOutputStream_blocking_read_Exception() throws IOException {
+        byte[] buf = new byte[1];
+        channel1.connect(this.localAddr1);
+        InputStream is = channel1.socket().getInputStream();
+        try {
+            is.read(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            is.read(buf, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        is.close();
+
+        try {
+            is.read(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            is.read(buf, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(buf, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            is.read(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void test_socket_getOutputStream_nonBlocking_write_Exception() throws IOException {
+        byte[] buf = new byte[1];
+        channel1.connect(this.localAddr1);
+        OutputStream os = channel1.socket().getOutputStream();
+        channel1.configureBlocking(false);
+
+        try {
+            os.write(1);
+            fail();
+        } catch (IllegalBlockingModeException expected) {
+        }
+        try {
+            os.write(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            os.write(buf, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        os.close();
+
+        try {
+            os.write(1);
+            fail();
+        } catch (IllegalBlockingModeException expected) {
+        }
+        try {
+            os.write(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            os.write(buf, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void test_socket_getOutputStream_blocking_write_Exception() throws IOException {
+        byte[] buf = new byte[1];
+        channel1.connect(this.localAddr1);
+        OutputStream os = channel1.socket().getOutputStream();
+        try {
+            os.write(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            os.write(buf, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        os.close();
+
+        try {
+            os.write(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+        try {
+            os.write(buf, -1, 1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 0, -1);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 0, 2);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(buf, 2, 0);
+            fail();
+        } catch (IndexOutOfBoundsException expected) {
+        }
+        try {
+            os.write(null, 0, 0);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    /**
+     * @tests SocketChannelImpl#socket().getOutputStream().write(int)
+     */
+    public void test_socket_getOutputStream_write_oneByte()
+            throws IOException {
+
+        // Regression test for Harmony-3475
+
+        int MAGIC = 123;
+
+        channel1.connect(this.localAddr1);
+
+        OutputStream os = channel1.socket().getOutputStream();
+
+        Socket acceptedSocket = server1.accept();
+
+        InputStream in = acceptedSocket.getInputStream();
+
+        os.write(MAGIC);
+        channel1.close();
+
+        int lastByte =  in.read();
+        if (lastByte == -1) {
+            fail("Server received nothing. Expected 1 byte.");
+        } else if (lastByte != MAGIC) {
+            fail("Server received wrong single byte: " + lastByte +
+                 ", expected: " + MAGIC);
+        }
+
+        lastByte = in.read();
+        if (lastByte != -1) {
+            fail("Server received too long sequence. Expected 1 byte.");
+        }
+    }
+
+    public void testSocket_setOptions() throws IOException {
+        channel1.connect(localAddr1);
+        Socket socket = channel1.socket();
+
+        ByteBuffer buffer = ByteBuffer.wrap(new byte[] {1, 2, 3});
+        socket.setKeepAlive(true);
+        channel1.write(buffer);
+
+        socket.setOOBInline(true);
+        channel1.write(buffer);
+
+        socket.setReceiveBufferSize(100);
+        channel1.write(buffer);
+
+        socket.setReuseAddress(true);
+        channel1.write(buffer);
+
+        socket.setSendBufferSize(100);
+        channel1.write(buffer);
+
+        socket.setSoLinger(true, 100);
+        channel1.write(buffer);
+
+        socket.setSoTimeout(1000);
+        channel1.write(buffer);
+
+        socket.setTcpNoDelay(true);
+        channel1.write(buffer);
+
+        socket.setTrafficClass(10);
+        channel1.write(buffer);
+    }
+
+    class MockSocketChannel extends SocketChannel{
+
+        private boolean isWriteCalled = false;
+
+        private boolean isReadCalled = false;
+
+        public MockSocketChannel(SelectorProvider provider){
+            super(provider);
+        }
+
+        public Socket socket() {
+            return null;
+        }
+
+        public boolean isConnected() {
+            return false;
+        }
+
+        public boolean isConnectionPending() {
+            return false;
+        }
+
+        public boolean connect(SocketAddress address) throws IOException {
+            return false;
+        }
+
+        public boolean finishConnect() throws IOException {
+            return false;
+        }
+
+        public int read(ByteBuffer target) throws IOException {
+            return 0;
+        }
+
+        public long read(ByteBuffer[] targets, int offset, int length) throws IOException {
+            // Verify that calling read(ByteBuffer[]) leads to the method
+            // read(ByteBuffer[], int, int) being called with a 0 for the
+            // second parameter and targets.length as the third parameter.
+            if(0 == offset && length == targets.length){
+                isReadCalled = true;
+            }
+            return 0;
+        }
+
+        public int write(ByteBuffer source) throws IOException {
+            return 0;
+        }
+
+        public long write(ByteBuffer[] sources, int offset, int length) throws IOException {
+            // Verify that calling write(ByteBuffer[]) leads to the method
+            // write(ByteBuffer[], int, int) being called with a 0 for the
+            // second parameter and sources.length as the third parameter.
+            if(0 == offset && length == sources.length){
+                isWriteCalled = true;
+            }
+            return 0;
+        }
+
+        protected void implCloseSelectableChannel() throws IOException {
+            // empty
+        }
+
+        protected void implConfigureBlocking(boolean blockingMode) throws IOException {
+            // empty
+        }
+
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SourceChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SourceChannelTest.java
new file mode 100644
index 0000000..53fdae4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SourceChannelTest.java
@@ -0,0 +1,554 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectionKey;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for java.nio.channels.Pipe.SourceChannel
+ */
+public class SourceChannelTest extends TestCase {
+
+	private static final int BUFFER_SIZE = 5;
+
+	private static final String ISO8859_1 = "ISO8859-1";
+
+	private Pipe pipe;
+
+	private Pipe.SinkChannel sink;
+
+	private Pipe.SourceChannel source;
+
+	private ByteBuffer buffer;
+
+	private ByteBuffer positionedBuffer;
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		pipe = Pipe.open();
+		sink = pipe.sink();
+		source = pipe.source();
+		buffer = ByteBuffer.wrap("bytes".getBytes(ISO8859_1));
+		positionedBuffer = ByteBuffer.wrap("12345bytes".getBytes(ISO8859_1));
+		positionedBuffer.position(BUFFER_SIZE);
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#validOps()
+	 */
+	public void test_validOps() {
+		assertEquals(SelectionKey.OP_READ, source.validOps());
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+	 */
+	public void test_read_LByteBuffer_DataAvailable() throws IOException {
+		// if anything can read, read method will not block
+		sink.write(ByteBuffer.allocate(1));
+		int count = source.read(ByteBuffer.allocate(10));
+		assertEquals(1, count);
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+	 */
+	public void test_read_LByteBuffer_Exception() throws IOException {
+		ByteBuffer nullBuf = null;
+		try {
+			source.read(nullBuf);
+            fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+	 */
+	public void test_read_LByteBuffer_SinkClosed() throws IOException {
+		ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+		sink.write(buffer);
+		sink.close();
+		long count = source.read(readBuf);
+		assertEquals(BUFFER_SIZE, count);
+		// readBuf is full, read 0 byte expected
+		count = source.read(readBuf);
+		assertEquals(0, count);
+		// readBuf is not null, -1 is expected
+		readBuf.position(0);
+		count = source.read(readBuf);
+		assertEquals(-1, count);
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+	 */
+	public void test_read_LByteBuffer_SourceClosed() throws IOException {
+		ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+		source.close();
+		try {
+			source.read(readBuf);
+            fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+		readBuf.position(BUFFER_SIZE);
+		try {
+			// readBuf is full
+			source.read(readBuf);
+            fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+
+		ByteBuffer nullBuf = null;
+		try {
+			source.read(nullBuf);
+            fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+        
+        ByteBuffer[] bufArray = null; 
+        try {
+            source.read(bufArray);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        
+        ByteBuffer[] nullBufArray = {nullBuf}; 
+        try {
+            source.read(nullBufArray);
+            fail("should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+	}
+
+	/**
+     * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer[])
+     */
+    public void test_read_$LByteBuffer() throws IOException {
+        ByteBuffer[] bufArray = { buffer, positionedBuffer };
+        boolean[] sinkBlockingMode = { true, true, false, false };
+        boolean[] sourceBlockingMode = { true, false, true, false };
+        for (int i = 0; i < sinkBlockingMode.length; ++i) {
+            // open new pipe everytime, will be closed in finally block
+            pipe = Pipe.open();
+            sink = pipe.sink();
+            source = pipe.source();
+            sink.configureBlocking(sinkBlockingMode[i]);
+            source.configureBlocking(sourceBlockingMode[i]);
+            buffer.position(0);
+            positionedBuffer.position(BUFFER_SIZE);
+            try {
+                long writeCount = sink.write(bufArray);
+                assertEquals(10, writeCount);
+                // invoke close to ensure all data will be sent out
+                sink.close();
+                // read until EOF is meet or readBufArray is full.
+                ByteBuffer[] readBufArray = { ByteBuffer.allocate(BUFFER_SIZE),
+                        ByteBuffer.allocate(BUFFER_SIZE) };
+                long totalCount = 0;
+                do {
+                    long count = source.read(readBufArray);
+                    if (count < 0) {
+                        break;
+                    }
+                    if (0 == count && BUFFER_SIZE == readBufArray[1].position()) {
+                        // source.read returns 0 because readBufArray is full
+                        break;
+                    }
+                    totalCount += count;
+                } while (totalCount <= 10);
+                // assert read result
+                for (ByteBuffer readBuf : readBufArray) {
+                    // RI may fail because of its bug implementation
+                    assertEquals(BUFFER_SIZE, readBuf.position());
+                    assertEquals("bytes",
+                            new String(readBuf.array(), ISO8859_1));
+                }
+            } finally {
+                // close pipe everytime
+                sink.close();
+                source.close();
+            }
+        }
+    }
+	
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+	 */
+	public void test_read_$LByteBuffer_Exception() throws IOException {
+		ByteBuffer[] nullBufArrayRef = null;
+		try {
+			source.read(nullBufArrayRef);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+
+		// ByteBuffer array contains null element
+		ByteBuffer nullBuf = null;
+		ByteBuffer[] nullBufArray1 = { nullBuf };
+		try {
+			source.read(nullBufArray1);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+
+		ByteBuffer[] nullBufArray2 = { buffer, nullBuf };
+		try {
+			source.read(nullBufArray2);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+	 */
+	public void test_read_$LByteBuffer_SinkClosed() throws IOException {
+		ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+		ByteBuffer[] readBufArray = { readBuf };
+		sink.write(buffer);
+		sink.close();
+		long count = source.read(readBufArray);
+		assertEquals(BUFFER_SIZE, count);
+		// readBuf is full, read 0 byte expected
+		count = source.read(readBufArray);
+		assertEquals(0, count);
+		// readBuf is not null, -1 is expected
+		readBuf.position(0);
+        assertTrue(readBuf.hasRemaining());
+		count = source.read(readBufArray);
+		assertEquals(-1, count);
+	}
+    
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+	 */
+	public void test_read_$LByteBuffer_SourceClosed() throws IOException {
+		ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+		ByteBuffer[] readBufArray = { readBuf };
+		source.close();
+		try {
+			source.read(readBufArray);
+            fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+		readBuf.position(BUFFER_SIZE);
+		try {
+			// readBuf is full
+			source.read(readBufArray);
+            fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+
+		ByteBuffer[] nullBufArrayRef = null;
+		try {
+			source.read(nullBufArrayRef);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+
+		// ByteBuffer array contains null element
+		ByteBuffer nullBuf = null;
+		ByteBuffer[] nullBufArray1 = { nullBuf };
+		try {
+			source.read(nullBufArray1);
+			fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+	}
+
+	/**
+     * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer[], int, int)
+     */
+    public void test_read_$LByteBufferII() throws IOException {
+        ByteBuffer[] bufArray = { buffer, positionedBuffer };
+        boolean[] sinkBlockingMode = { true, true, false, false };
+        boolean[] sourceBlockingMode = { true, false, true, false };
+        for (int i = 0; i < sinkBlockingMode.length; ++i) {
+            Pipe pipe = Pipe.open();
+            sink = pipe.sink();
+            source = pipe.source();
+
+            sink.configureBlocking(sinkBlockingMode[i]);
+            source.configureBlocking(sourceBlockingMode[i]);
+
+            buffer.position(0);
+            positionedBuffer.position(BUFFER_SIZE);
+            try {
+                sink.write(bufArray);
+                // invoke close to ensure all data will be sent out
+                sink.close();
+                // read until EOF is meet or readBufArray is full.
+                ByteBuffer[] readBufArray = { ByteBuffer.allocate(BUFFER_SIZE),
+                        ByteBuffer.allocate(BUFFER_SIZE) };
+                long totalCount = 0;
+                do {
+                    long count = source.read(readBufArray, 0, 2);
+                    if (count < 0) {
+                        break;
+                    }
+                    if (0 == count && BUFFER_SIZE == readBufArray[1].position()) {
+                        // source.read returns 0 because readBufArray is full
+                        break;
+                    }
+                    totalCount += count;
+                } while (totalCount != 10);
+
+                // assert read result
+                for (ByteBuffer readBuf : readBufArray) {
+                    // RI may fail because of its bug implementation
+                    assertEquals(BUFFER_SIZE, readBuf.position());
+                    assertEquals("bytes",
+                            new String(readBuf.array(), ISO8859_1));
+                }
+            } finally {
+                sink.close();
+                source.close();
+            }
+        }
+    }
+
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+	 */
+	public void test_read_$LByteBufferII_Exception() throws IOException {
+
+		ByteBuffer[] nullBufArrayRef = null;
+		try {
+			source.read(nullBufArrayRef, 0, 1);
+			fail();
+		} catch (NullPointerException expected) {
+		}
+
+		try {
+			source.read(nullBufArrayRef, 0, -1);
+			fail();
+		} catch (NullPointerException expected) {
+		} catch (IndexOutOfBoundsException expected) {
+		}
+
+		try {
+			source.read(new ByteBuffer[0], 0, -1);
+			fail();
+		} catch (IndexOutOfBoundsException expected) {
+		}
+
+		try {
+			source.read(new ByteBuffer[0], -1, 0);
+			fail();
+		} catch (IndexOutOfBoundsException expected) {
+		}
+
+		// ByteBuffer array contains null element
+		ByteBuffer nullBuf = null;
+		ByteBuffer[] nullBufArray1 = { nullBuf };
+		try {
+			source.read(nullBufArray1, 0, 1);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+		try {
+			source.read(nullBufArray1, 0, -1);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			source.read(nullBufArray1, -1, 0);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			source.read(nullBufArray1, -1, 1);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+
+		ByteBuffer[] nullBufArray2 = { buffer, nullBuf };
+
+		try {
+			source.read(nullBufArray1, 1, -1);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+
+		try {
+			source.read(nullBufArray2, 0, 3);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+
+		try {
+			source.read(nullBufArray2, 0, 2);
+			fail("should throw NullPointerException");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+	 */
+	public void test_read_$LByteBufferII_SinkClosed() throws IOException {
+		ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+		ByteBuffer[] readBufArray = { readBuf };
+		sink.write(buffer);
+		sink.close();
+		long count = source.read(readBufArray, 0, 1);
+		assertEquals(BUFFER_SIZE, count);
+		// readBuf is full, read 0 byte expected
+		count = source.read(readBufArray);
+		assertEquals(0, count);
+		// readBuf is not null, -1 is expected
+		readBuf.position(0);
+		count = source.read(readBufArray, 0, 1);
+		assertEquals(-1, count);
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+	 */
+	public void test_read_$LByteBufferII_SourceClosed() throws IOException {
+		ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+		ByteBuffer[] readBufArray = { readBuf };
+		source.close();
+		try {
+			source.read(readBufArray, 0, 1);
+			fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+		readBuf.position(BUFFER_SIZE);
+		try {
+			// readBuf is full
+			source.read(readBufArray, 0, 1);
+			fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+
+		ByteBuffer[] nullBufArrayRef = null;
+		try {
+			source.read(nullBufArrayRef, 0, 1);
+			fail();
+		} catch (NullPointerException expected) {
+		}
+
+		try {
+			source.read(nullBufArrayRef, 0, -1);
+			fail();
+		} catch (NullPointerException expected) {
+		} catch (IndexOutOfBoundsException expected) {
+		}
+
+		try {
+			source.read(new ByteBuffer[0], 0, -1);
+			fail();
+		} catch (IndexOutOfBoundsException expected) {
+		}
+
+		try {
+			source.read(new ByteBuffer[0], -1, 1);
+			fail();
+		} catch (IndexOutOfBoundsException expected) {
+		}
+
+		// ByteBuffer array contains null element
+		ByteBuffer nullBuf = null;
+		ByteBuffer[] nullBufArray1 = { nullBuf };
+		try {
+			source.read(nullBufArray1, 0, 1);
+			fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+		try {
+			source.read(nullBufArray1, 0, -1);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			source.read(nullBufArray1, -1, 0);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+		try {
+			source.read(nullBufArray1, -1, 1);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+
+		ByteBuffer[] nullBufArray2 = { buffer, nullBuf };
+
+		try {
+			source.read(nullBufArray1, 1, -1);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+
+		try {
+			source.read(nullBufArray2, 0, 3);
+			fail("should throw IndexOutOfBoundsException");
+		} catch (IndexOutOfBoundsException e) {
+			// expected
+		}
+
+		try {
+			source.read(nullBufArray2, 0, 2);
+			fail("should throw ClosedChannelException");
+		} catch (ClosedChannelException e) {
+			// expected
+		}
+	}
+
+	/**
+	 * @tests java.nio.channels.Pipe.SourceChannel#close()
+	 */
+	public void test_close() throws IOException {
+		sink.close();
+		assertFalse(sink.isOpen());
+	}
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnixSelectorTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnixSelectorTest.java
new file mode 100644
index 0000000..8995394
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnixSelectorTest.java
@@ -0,0 +1,116 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import junit.framework.TestCase;
+
+public class UnixSelectorTest extends TestCase {
+    static class Server {
+        ServerSocketChannel serverChannel = ServerSocketChannel.open();
+        ServerSocket socket = null;
+
+        Server() throws Exception {
+            serverChannel.configureBlocking(false);
+        }
+
+        public void initialize() throws Exception {
+            this.socket = serverChannel.socket();
+            socket.bind(null);
+        }
+
+        public void accept() {
+            Thread serverThread = new Thread(new Runnable() {
+                public void run() {
+                    try {
+                        while (serverChannel.accept() == null) {
+                            Thread.sleep(1000);
+                        }
+                    } catch (Exception e) {}
+                }
+            });
+            serverThread.start();
+        }
+
+        public void close() throws Exception{
+            serverChannel.close();
+        }
+    }
+
+    public void testSelectorAcceptAndRead() throws Exception {
+        Selector sel0 = Selector.open();
+        Selector sel1 = Selector.open();
+        Server server = new Server();
+        SelectionKey mkey0 = server.serverChannel.register(sel0, SelectionKey.OP_ACCEPT);
+        server.serverChannel.register(sel1, SelectionKey.OP_ACCEPT);
+
+        // HUP is treating as acceptable
+        assertEquals(1, sel0.select(100));
+        assertEquals(true, sel0.selectedKeys().contains(mkey0));
+        server.initialize();
+        // after bind can not accept
+        assertEquals(0, sel1.select(100));
+        server.accept();
+        Thread.sleep(1000);
+        SocketChannel socketChannel = SocketChannel.open();
+        socketChannel.configureBlocking(false);
+        Selector sel2 = Selector.open();
+        socketChannel.register(sel2, SelectionKey.OP_WRITE);
+        boolean isConnected = socketChannel.connect(server.socket.getLocalSocketAddress());
+        if (!isConnected) {
+            socketChannel.finishConnect();
+        }
+
+        assertEquals(true, socketChannel.isConnected());
+        server.close();
+        Thread.sleep(3000);
+        assertEquals(true, socketChannel.isConnected());
+        assertEquals(1, sel2.select(100));
+    }
+
+    public void testSelectUnConnectedChannel() throws Exception {
+        SocketChannel socketChannel2 = SocketChannel.open();
+        socketChannel2.configureBlocking(false);
+        Selector sel3 = Selector.open();
+        SelectionKey mkey3 = socketChannel2.register(sel3, SelectionKey.OP_WRITE);
+        // HUP is also treating as writable
+        assertEquals(1, sel3.select(100));
+        assertEquals(false, mkey3.isConnectable());
+        // even the channel is not connected, the selector could be writable
+        assertEquals(false, socketChannel2.isConnected());
+        assertEquals(true, mkey3.isWritable());
+
+        Selector sel4 = Selector.open();
+        SelectionKey mkey4 = socketChannel2.register(sel4, SelectionKey.OP_CONNECT);
+        assertEquals(1, sel4.select(100));
+        assertEquals(false, mkey4.isWritable());
+        assertEquals(true, mkey4.isConnectable());
+
+        Selector sel5 = Selector.open();
+        SelectionKey mkey5 = socketChannel2.register(sel5, SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE);
+        assertEquals(1, sel5.select(100));
+        assertEquals(true, mkey5.isWritable());
+        assertEquals(true, mkey5.isConnectable());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java
new file mode 100644
index 0000000..827dcd7
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java
@@ -0,0 +1,54 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.UnresolvedAddressException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for UnresolvedAddressException
+ */
+public class UnresolvedAddressExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.UnresolvedAddressException#UnresolvedAddressException()}
+     */
+    public void test_Constructor() {
+        UnresolvedAddressException e = new UnresolvedAddressException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new UnresolvedAddressException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new UnresolvedAddressException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java
new file mode 100644
index 0000000..e032ea4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java
@@ -0,0 +1,55 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.UnsupportedAddressTypeException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for UnsupportedAddressTypeException
+ */
+public class UnsupportedAddressTypeExceptionTest extends TestCase {
+    
+    /**
+     * @tests {@link java.nio.channels.UnsupportedAddressTypeException#UnsupportedAddressTypeException()}
+     */
+    public void test_Constructor() {
+        UnsupportedAddressTypeException e = new UnsupportedAddressTypeException();
+        assertNull(e.getMessage());
+        assertNull(e.getLocalizedMessage());
+        assertNull(e.getCause());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new UnsupportedAddressTypeException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this,
+                new UnsupportedAddressTypeException());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractInterruptibleChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractInterruptibleChannelTest.java
new file mode 100644
index 0000000..5072dc9
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractInterruptibleChannelTest.java
@@ -0,0 +1,135 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+
+import junit.framework.TestCase;
+
+public class AbstractInterruptibleChannelTest extends TestCase {
+    
+    /**
+     * @tests AbstractInterruptibleChannel#close()
+     */
+    public void test_close() throws IOException {
+        MockInterruptibleChannel testMiChannel = new MockInterruptibleChannel();
+        assertTrue(testMiChannel.isOpen());
+        testMiChannel.isImplCloseCalled = false;
+        testMiChannel.close();
+        assertTrue(testMiChannel.isImplCloseCalled);
+        assertFalse(testMiChannel.isOpen());
+    }
+
+    /**
+     * @tests AbstractInterruptibleChannel#begin/end()
+     */
+    public void test_begin_end() throws IOException {
+        boolean complete = false;
+        MockInterruptibleChannel testChannel = new MockInterruptibleChannel();
+        try {
+            testChannel.superBegin();
+            complete = true;
+        } finally {
+            testChannel.superEnd(complete);
+        }
+
+        try {
+            testChannel.superBegin();
+            complete = false;
+        } finally {
+            testChannel.superEnd(complete);
+        }
+        
+        try {
+            testChannel.superBegin();
+            complete = true;
+        } finally {
+            testChannel.superEnd(complete);
+        }
+        
+        testChannel.superBegin();
+        try {
+            testChannel.superBegin();
+            complete = true;
+        } finally {
+            testChannel.superEnd(complete);
+        }
+        assertTrue(testChannel.isOpen());
+        testChannel.close();
+    }
+
+    /**
+     * @tests AbstractInterruptibleChannel#close/begin/end()
+     */
+    public void test_close_begin_end() throws IOException {
+        boolean complete = false;
+        MockInterruptibleChannel testChannel = new MockInterruptibleChannel();
+        assertTrue(testChannel.isOpen());
+        try {
+            testChannel.superBegin();
+            complete = true;
+        } finally {
+            testChannel.superEnd(complete);
+        }
+        assertTrue(testChannel.isOpen());
+        testChannel.close();
+        try {
+            testChannel.superBegin();
+            complete = false;
+        } finally {
+            try {
+                testChannel.superEnd(complete);
+                fail("should throw AsynchronousCloseException");
+            } catch (AsynchronousCloseException e) {
+                // expected
+            }
+        }
+        assertFalse(testChannel.isOpen());
+        try {
+            testChannel.superBegin();
+            complete = true;
+        } finally {
+            testChannel.superEnd(complete);
+        }
+        assertFalse(testChannel.isOpen());
+    }
+    
+    private class MockInterruptibleChannel extends AbstractInterruptibleChannel {
+
+        private boolean isImplCloseCalled = false;
+        
+        public MockInterruptibleChannel() {
+            super();
+        }
+
+        protected void implCloseChannel() throws IOException {
+        	isImplCloseCalled = true; 
+        }
+
+        // call super.begin() for test
+        void superBegin() {
+            super.begin();
+        }
+        
+        // call super.end() for test
+        void superEnd(boolean completed) throws AsynchronousCloseException {
+            super.end(completed);
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
new file mode 100644
index 0000000..b396264
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
@@ -0,0 +1,313 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.IllegalSelectorException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for AbstractSelectableChannel 
+ */
+public class AbstractSelectableChannelTest extends TestCase {
+
+    private MockSelectableChannel testChannel;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        testChannel = new MockSelectableChannel(SelectorProvider.provider());
+    }
+
+    protected void tearDown() throws Exception {
+        if (testChannel.isOpen()) {
+            testChannel.close();
+        }
+    }
+
+    /**
+     * @tests AbstractSelectableChannel#implCloseChannel()
+     */
+    public void test_implClose() throws IOException {
+        testChannel.isImplCloseSelectableChannelCalled = false;
+        testChannel.implCloseSelectableChannelCount = 0;
+        testChannel.close();
+        assertFalse(testChannel.isOpen());
+        assertTrue(testChannel.isImplCloseSelectableChannelCalled);
+        assertEquals(1, testChannel.implCloseSelectableChannelCount);
+
+        testChannel = new MockSelectableChannel(SelectorProvider.provider());
+        testChannel.isImplCloseSelectableChannelCalled = false;
+        testChannel.implCloseSelectableChannelCount = 0;
+        // close twice.
+        // make sure implCloseSelectableChannelCount is called only once.
+        testChannel.close();
+        testChannel.close();
+        assertFalse(testChannel.isOpen());
+        assertTrue(testChannel.isImplCloseSelectableChannelCalled);
+        assertEquals(1, testChannel.implCloseSelectableChannelCount);
+    }
+
+    /**
+     * @tests AbstractSelectableChannel#provider()
+     */
+    public void test_provider() {
+        SelectorProvider provider = testChannel.provider();
+        assertSame(SelectorProvider.provider(), provider);
+        testChannel = new MockSelectableChannel(null);
+        provider = testChannel.provider();
+        assertNull(provider);
+    }
+
+    /**
+     * @tests AbstractSelectableChannel#isBlocking()
+     */
+    public void test_isBlocking() throws IOException {
+        assertTrue(testChannel.isBlocking());
+        testChannel.configureBlocking(false);
+        assertFalse(testChannel.isBlocking());
+        testChannel.configureBlocking(true);
+        assertTrue(testChannel.isBlocking());
+    }
+
+    /**
+     * 
+     * @tests AbstractSelectableChannel#blockingLock()
+     */
+    public void test_blockingLock() {
+        Object gotObj = testChannel.blockingLock();
+        assertNotNull(gotObj);
+    }
+
+    /**
+     * @tests AbstractSelectableChannel#register(Selector, int, Object)
+     */
+    public void test_register_LSelectorILObject() throws IOException {
+        assertFalse(testChannel.isRegistered());
+        Selector acceptSelector1 = SelectorProvider.provider().openSelector();
+        Selector acceptSelector2 = new MockAbstractSelector(SelectorProvider
+                .provider());
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        SelectionKey acceptKey = sc.register(acceptSelector1,
+                SelectionKey.OP_READ, null);
+        assertNotNull(acceptKey);
+        assertTrue(acceptKey.isValid());
+        assertSame(sc, acceptKey.channel());
+
+        //test that sc.register invokes Selector.register()
+        acceptKey = sc.register(acceptSelector2, SelectionKey.OP_READ, null);
+        assertNull(acceptKey);
+        
+        // Regression test to ensure acceptance of a selector with empty
+        // interest set.
+        SocketChannel channel = SocketChannel.open();
+        channel.configureBlocking(false);
+        Selector selector = Selector.open();
+        channel.register(selector, 0);
+        selector.close();
+        channel.close();
+    }
+
+    /**
+     * @tests AbstractSelectableChannel#register(Selector, int, Object)
+     */
+    public void test_register_LSelectorILObject_IllegalArgument()
+            throws IOException {
+        Selector acceptSelector = SelectorProvider.provider().openSelector();
+        assertTrue(acceptSelector.isOpen());
+        MockSelectableChannel msc = new MockSelectableChannel(SelectorProvider
+                .provider());
+        msc.configureBlocking(false);
+        // in nonblocking mode
+        try {
+            //different SelectionKey with validOps
+            msc.register(acceptSelector, SelectionKey.OP_READ, null);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            msc.register(null, 0, null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        // in nonblocking mode, if selector closed
+        acceptSelector.close();
+        try {
+            msc.register(acceptSelector, SelectionKey.OP_READ, null);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            msc.register(null, 0, null);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            msc.register(acceptSelector, 0, null);
+            fail("Should throw IllegalSelectorException");
+        } catch (IllegalSelectorException e) {
+            // expected
+        }
+
+        acceptSelector = SelectorProvider.provider().openSelector();
+        // test in blocking mode
+        msc.configureBlocking(true);
+        try {
+            msc.register(acceptSelector, SelectionKey.OP_READ, null);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            msc.register(null, 0, null);
+            fail("Should throw IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+        acceptSelector.close();
+        // in blocking mode, if selector closed
+        try {
+            msc.register(acceptSelector, SelectionKey.OP_READ, null);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            msc.register(null, 0, null);
+            fail("Should throw IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+
+        // register with an object
+        Object argObj = new Object();
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        try {
+            sc.register(null, SelectionKey.OP_READ, argObj);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+
+        // if channel closed
+        msc.close();
+        try {
+            msc.register(acceptSelector, SelectionKey.OP_READ, null);
+            fail("Should throw ClosedChannelException");
+        } catch (ClosedChannelException e) {
+            // expected
+        }
+
+    }
+
+    /**
+     * @tests AbstractSelectableChannel#keyFor(Selector)
+     */
+    public void test_keyfor_LSelector() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        Object argObj = new Object();
+        sc.configureBlocking(false);
+        Selector acceptSelector = SelectorProvider.provider().openSelector();
+        Selector acceptSelectorOther = SelectorProvider.provider()
+                .openSelector();
+        SelectionKey acceptKey = sc.register(acceptSelector,
+                SelectionKey.OP_READ, argObj);
+        assertEquals(sc.keyFor(acceptSelector), acceptKey);
+        SelectionKey acceptKeyObjNull = sc.register(acceptSelector,
+                SelectionKey.OP_READ, null);
+        assertSame(sc.keyFor(acceptSelector), acceptKeyObjNull);
+        assertSame(acceptKeyObjNull, acceptKey);
+        SelectionKey acceptKeyOther = sc.register(acceptSelectorOther,
+                SelectionKey.OP_READ, null);
+        assertSame(sc.keyFor(acceptSelectorOther), acceptKeyOther);
+    }
+
+    /**
+     * @tests AbstractSelectableChannel#configureBlocking(boolean)
+     */
+    public void test_configureBlocking_Z_IllegalBlockingMode() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
+        Selector acceptSelector = SelectorProvider.provider().openSelector();
+        SelectionKey acceptKey = sc.register(acceptSelector,
+                SelectionKey.OP_READ, null);
+        assertEquals(sc.keyFor(acceptSelector), acceptKey);
+        SelectableChannel getChannel = sc.configureBlocking(false);
+        assertEquals(getChannel, sc);
+        try {
+            sc.configureBlocking(true);
+            fail("Should throw IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests AbstractSelectableChannel#configureBlocking(boolean)
+     */
+    public void test_configureBlocking_Z() throws Exception {
+        MockSelectableChannel mock = new MockSelectableChannel(SelectorProvider
+                .provider());
+        //default blocking mode is true
+        //the implConfigureBlocking is only invoked if the given mode is different with current one
+        mock.configureBlocking(true);
+        assertFalse(mock.implConfigureBlockingCalled);
+        mock.configureBlocking(false);
+        assertTrue(mock.implConfigureBlockingCalled);
+    }
+
+    private class MockSelectableChannel extends AbstractSelectableChannel {
+
+        private boolean isImplCloseSelectableChannelCalled = false;
+
+        private int implCloseSelectableChannelCount = 0;
+
+        private boolean implConfigureBlockingCalled = false;
+
+        public MockSelectableChannel(SelectorProvider arg0) {
+            super(arg0);
+        }
+
+        protected void implCloseSelectableChannel() throws IOException {
+            isImplCloseSelectableChannelCalled = true;
+            ++implCloseSelectableChannelCount;
+        }
+
+        protected void implConfigureBlocking(boolean arg0) throws IOException {
+            implConfigureBlockingCalled = true;
+        }
+
+        public int validOps() {
+            return SelectionKey.OP_ACCEPT;
+        }
+
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectionKeyTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectionKeyTest.java
new file mode 100644
index 0000000..1404fc1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectionKeyTest.java
@@ -0,0 +1,76 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectionKey;
+
+import junit.framework.TestCase;
+
+public class AbstractSelectionKeyTest extends TestCase {
+
+    /**
+     * @tests AbstractSelectionKey#isValid() without selector
+     */
+    public void test_isValid() throws Exception {
+        MockSelectionKey testKey = new MockSelectionKey();
+        assertTrue(testKey.isValid());
+    }
+
+    /**
+     * @tests AbstractSelectionKey#cancel
+     */
+    public void test_cancel() throws Exception {
+        MockSelectionKey testKey = new MockSelectionKey();
+        try {
+            testKey.cancel();
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected: no selector available
+        }
+        assertFalse(testKey.isValid());
+    }
+
+    private class MockSelectionKey extends AbstractSelectionKey {
+
+        MockSelectionKey() {
+            super();
+        }
+
+        public SelectableChannel channel() {
+            return null;
+        }
+
+        public Selector selector() {
+            return null;
+        }
+
+        public int interestOps() {
+            return 0;
+        }
+
+        public SelectionKey interestOps(int arg0) {
+            return null;
+        }
+
+        public int readyOps() {
+            return 0;
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectorTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectorTest.java
new file mode 100644
index 0000000..4b39001
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectorTest.java
@@ -0,0 +1,160 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for AbstractSelector and register of its default implementation
+ */ 
+public class AbstractSelectorTest extends TestCase {
+
+    /**
+     * @tests AbstractSelector#provider()
+     */
+    public void test_provider() throws IOException {
+        Selector mockSelector = new MockAbstractSelector(SelectorProvider
+                .provider());
+        assertTrue(mockSelector.isOpen());
+        assertSame(SelectorProvider.provider(), mockSelector.provider());
+        mockSelector = new MockAbstractSelector(null);
+        assertNull(mockSelector.provider());
+    }
+
+    /**
+     * @tests AbstractSelector#close()
+     */
+    public void test_close() throws IOException {
+        MockAbstractSelector mockSelector = new MockAbstractSelector(
+                SelectorProvider.provider());
+        mockSelector.close();
+        assertTrue(mockSelector.isImplCloseSelectorCalled);
+    }
+
+    /**
+     * 
+     * @tests AbstractSelector#begin/end()
+     */
+    public void test_begin_end() throws IOException {
+        MockAbstractSelector mockSelector = new MockAbstractSelector(
+                SelectorProvider.provider());     
+        try {
+            mockSelector.superBegin();
+        } finally {
+            mockSelector.superEnd();
+        }
+        
+        mockSelector = new MockAbstractSelector(SelectorProvider.provider());
+        try {
+            mockSelector.superBegin();
+            mockSelector.close();
+        } finally {
+            mockSelector.superEnd();
+        }
+       
+        try {
+            // begin twice
+            mockSelector.superBegin();
+            mockSelector.superBegin();
+        } finally {
+            mockSelector.superEnd();
+        }
+        
+        try {
+            mockSelector.superBegin();
+        } finally {
+            // end twice
+            mockSelector.superEnd();
+            mockSelector.superEnd();
+        }
+
+        mockSelector.close();
+        try {
+            mockSelector.superBegin();
+        } finally {
+            mockSelector.superEnd();
+        }
+    }
+    
+    /**
+     * @tests AbstractSelector#isOpen()
+     */
+    public void test_isOpen() throws Exception {
+        Selector acceptSelector = SelectorProvider.provider().openSelector();
+        assertTrue(acceptSelector.isOpen());
+        acceptSelector.close();
+        assertFalse(acceptSelector.isOpen());
+    }
+    
+    /**
+     * @tests AbstractSelector#register(Selector,int)
+     */
+    public void test_register_LSelectorI() throws Exception {
+        Selector acceptSelector = SelectorProvider.provider().openSelector();
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.configureBlocking(false);
+
+        assertFalse(ssc.isRegistered());
+        SelectionKey acceptKey = ssc.register(acceptSelector,
+                SelectionKey.OP_ACCEPT);
+        assertTrue(ssc.isRegistered());
+        assertNotNull(acceptKey);
+        assertTrue(acceptSelector.keys().contains(acceptKey));
+    }
+
+    /**
+     * @tests AbstractSelector#register(Selector,int)
+     */
+    public void test_register_LSelectorI_error() throws IOException {
+        Selector acceptSelector = SelectorProvider.provider().openSelector();
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.configureBlocking(false);
+        acceptSelector.close();
+
+        assertFalse(acceptSelector.isOpen());
+        try {
+            ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        assertFalse(ssc.isRegistered());
+
+        acceptSelector = Selector.open();
+        ssc.configureBlocking(true);
+        try {
+            ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
+            fail("should throw IllegalBlockingModeException");
+        } catch (IllegalBlockingModeException e) {
+            // expected
+        }
+        assertFalse(ssc.isRegistered());
+        ssc.configureBlocking(false);
+        SelectionKey acceptKey = ssc.register(acceptSelector,
+                SelectionKey.OP_ACCEPT);
+        assertNotNull(acceptKey);
+        assertTrue(acceptSelector.keys().contains(acceptKey));
+        assertTrue(ssc.isRegistered());
+    }    
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/MockAbstractSelector.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/MockAbstractSelector.java
new file mode 100644
index 0000000..6e016b0
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/MockAbstractSelector.java
@@ -0,0 +1,89 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelectionKey;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Set;
+
+public class MockAbstractSelector extends AbstractSelector {
+
+    public boolean isImplCloseSelectorCalled = false;
+    
+	public MockAbstractSelector(SelectorProvider arg0) {
+		super(arg0);
+	}
+
+	public static MockAbstractSelector openSelector() {
+		return new MockAbstractSelector(SelectorProvider.provider());
+	}
+
+	public Set getCancelledKeys() {
+		return super.cancelledKeys();
+	}
+
+	protected void implCloseSelector() throws IOException {
+        isImplCloseSelectorCalled = true;
+	}
+
+	protected SelectionKey register(AbstractSelectableChannel arg0, int arg1,
+			Object arg2) {
+		return null;
+	}
+
+	public void superBegin() {
+		super.begin();
+	}
+
+	public void superEnd() {
+		super.end();
+	}
+
+	protected void mockDeregister(AbstractSelectionKey key) {
+		super.deregister(key);
+	}
+
+	public Set<SelectionKey> keys() {
+		return null;
+	}
+
+	public Set<SelectionKey> selectedKeys() {
+		return null;
+	}
+
+	public int selectNow() throws IOException {
+		return 0;
+	}
+
+	public int select(long arg0) throws IOException {
+		return 0;
+	}
+
+	public int select() throws IOException {
+		return 0;
+	}
+
+	public Selector wakeup() {
+		return null;
+	}
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
new file mode 100644
index 0000000..6f59190
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
@@ -0,0 +1,453 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+public class ASCIICharsetEncoderTest extends TestCase {
+
+	// charset for ascii
+	private static final Charset cs = Charset.forName("ascii");
+    private static final CharsetEncoder encoder = cs.newEncoder();
+    private static final int MAXCODEPOINT = 0x7F; 
+	/*
+	 * @see CharsetEncoderTest#setUp()
+	 */
+	protected void setUp() throws Exception {
+    }
+
+	/*
+	 * @see CharsetEncoderTest#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+    }
+
+	public void testCanEncodeCharSequence() {
+		// normal case for ascCS
+		assertTrue(encoder.canEncode("\u0077"));
+		assertFalse(encoder.canEncode("\uc2a3"));
+		assertFalse(encoder.canEncode("\ud800\udc00"));
+		try {
+			encoder.canEncode(null);
+		} catch (NullPointerException e) {
+		}
+		assertTrue(encoder.canEncode(""));
+	}
+
+	public void testCanEncodeSurrogate () {
+		assertFalse(encoder.canEncode('\ud800'));
+		assertFalse(encoder.canEncode("\udc00"));
+	}
+
+	public void testCanEncodechar() throws CharacterCodingException {
+		assertTrue(encoder.canEncode('\u0077'));
+		assertFalse(encoder.canEncode('\uc2a3'));
+	}
+
+	public void testSpecificDefaultValue() {
+		assertEquals(1.0, encoder.averageBytesPerChar(), 0.0);
+		assertEquals(1.0, encoder.maxBytesPerChar(), 0.0);
+	}
+
+	public void testMultiStepEncode() throws CharacterCodingException {
+		encoder.onMalformedInput(CodingErrorAction.REPORT);
+		encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+		try {
+			encoder.encode(CharBuffer.wrap("\ud800\udc00"));
+			fail("should unmappable");
+		} catch (UnmappableCharacterException e) {
+		}
+		encoder.reset();
+		ByteBuffer out = ByteBuffer.allocate(10);
+		assertTrue(encoder.encode(CharBuffer.wrap("\ud800"), out, true)
+				.isMalformed());
+		encoder.flush(out);
+		encoder.reset();
+		out = ByteBuffer.allocate(10);
+		assertSame(CoderResult.UNDERFLOW, encoder.encode(CharBuffer
+				.wrap("\ud800"), out, false));
+		assertTrue(encoder.encode(CharBuffer.wrap("\udc00"), out, true)
+				.isMalformed());
+	}
+
+    public void testEncodeMapping() throws CharacterCodingException {
+        encoder.reset();
+        
+        for (int i =0; i <= MAXCODEPOINT; i++) {
+            char[] chars = Character.toChars(i);
+            CharBuffer cb = CharBuffer.wrap(chars);
+            ByteBuffer bb = encoder.encode(cb);
+            assertEquals(i, bb.get(0));
+        }
+        
+        CharBuffer cb = CharBuffer.wrap("\u0080");
+        try {
+            encoder.encode(cb);
+        } catch (UnmappableCharacterException e) {
+            //expected
+        }
+        
+        cb = CharBuffer.wrap("\ud800");
+        try {
+            encoder.encode(cb);
+        } catch (MalformedInputException e) {
+            //expected
+        }
+
+        ByteBuffer bb = ByteBuffer.allocate(0x10);
+        cb = CharBuffer.wrap("A");
+        encoder.reset();
+        encoder.encode(cb, bb, false);
+        try {
+        encoder.encode(cb);
+        } catch (IllegalStateException e) {
+            //expected
+        }
+    }
+    
+    public void testInternalState() {
+        CharBuffer in = CharBuffer.wrap("A");
+        ByteBuffer out = ByteBuffer.allocate(0x10);
+        
+        //normal encoding process
+        encoder.reset();
+        encoder.encode(in, out, false);
+        in = CharBuffer.wrap("B");
+        encoder.encode(in, out, true);
+        encoder.flush(out);
+    }
+    
+    //reset could be called at any time
+    public void testInternalState_Reset() {
+        CharsetEncoder newEncoder = cs.newEncoder();
+        //Init - > reset
+        newEncoder.reset();
+        
+        //reset - > reset
+        newEncoder.reset();
+
+        //encoding - >reset
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, false);
+            newEncoder.reset();
+        }
+
+        //encoding end -> reset
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            newEncoder.reset();
+        }
+        //flused -> reset
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            newEncoder.flush(out);
+            newEncoder.reset();
+        }
+    }
+    
+    public void testInternalState_Encoding() {
+        CharsetEncoder newEncoder = cs.newEncoder();
+        //Init - > encoding
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, false);
+        }
+        
+        //reset - > encoding
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.reset();            
+            newEncoder.encode(in, out, false);
+        }
+        //reset - > encoding - > encoding
+        {
+            newEncoder.reset();            
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, false);
+            in = CharBuffer.wrap("BC");
+            newEncoder.encode(in, out, false);
+        }
+        
+        //encoding_end - > encoding
+        {
+            newEncoder.reset();            
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            in = CharBuffer.wrap("BC");
+            try {
+                newEncoder.encode(in, out, false);
+                fail("Should throw IllegalStateException");
+            } catch (IllegalStateException e) {
+                //expected
+            }
+        }
+        //flushed - > encoding
+        {
+            newEncoder.reset();            
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            newEncoder.flush(out);
+            in = CharBuffer.wrap("BC");
+            try {
+                newEncoder.encode(in, out, false);
+                fail("Should throw IllegalStateException");
+            } catch (IllegalStateException e) {
+                //expected
+            }
+        }
+    }
+    
+    public void testInternalState_Encoding_END() {
+        CharsetEncoder newEncoder = cs.newEncoder();
+
+        //Init - >encoding_end
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+        }
+        
+        //Reset -> encoding_end
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.reset();
+            newEncoder.encode(in, out, true);
+        }
+
+        //encoding -> encoding_end
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, false);
+            in = CharBuffer.wrap("BC");
+            newEncoder.encode(in, out, true);
+        }
+        
+        //Reset -> encoding_end
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            in = CharBuffer.wrap("BC");
+            newEncoder.encode(in, out, true);
+        }
+        
+        //Flushed -> encoding_end
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            newEncoder.flush(out);
+            in = CharBuffer.wrap("BC");
+            try {
+                newEncoder.encode(in, out, true);
+                fail("Should throw IllegalStateException");
+            } catch (IllegalStateException e) {
+                //expected
+            }
+        }
+    }
+    
+    public void testInternalState_Flushed() {
+        CharsetEncoder newEncoder = cs.newEncoder();
+        
+        // init -> flushed
+		{
+			ByteBuffer out = ByteBuffer.allocate(0x10);
+			try {
+				newEncoder.flush(out);
+				fail("Should throw IllegalStateException");
+			} catch (IllegalStateException e) {
+				//expected
+			}
+
+		}
+
+        // reset - > flushed
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            newEncoder.reset();
+            try {
+                newEncoder.flush(out);
+				fail("Should throw IllegalStateException");
+            } catch (IllegalStateException e) {
+                //expected
+            }
+        }
+        
+        //encoding - > flushed
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, false);
+            try {
+
+                newEncoder.flush(out);
+                fail("Should throw IllegalStateException");
+            } catch (IllegalStateException e) {
+                // expected
+            }
+        }
+        
+        //encoding_end -> flushed
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            newEncoder.flush(out);
+        }
+        
+        //flushd - > flushed
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            newEncoder.flush(out);
+            try {
+                newEncoder.flush(out);
+                fail("Should throw IllegalStateException");
+            } catch (IllegalStateException e) {
+                // expected
+            }
+        }
+    }
+    
+    public void testInternalState_Encode() throws CharacterCodingException {
+        CharsetEncoder newEncoder = cs.newEncoder();
+        //Init - > encode
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            newEncoder.encode(in);
+        }
+        
+        //Reset - > encode
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            newEncoder.encode(in);
+        }
+        
+        //Encoding -> encode
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, false);
+            in = CharBuffer.wrap("BC");
+            newEncoder.encode(in);
+        }
+        
+        //Encoding_end -> encode
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            in = CharBuffer.wrap("BC");
+            newEncoder.encode(in);
+        }
+        
+        //Flushed -> reset
+        {
+            newEncoder.reset();
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+            in = CharBuffer.wrap("BC");
+            newEncoder.flush(out);
+            out = newEncoder.encode(in);
+        }
+    }
+    
+    public void testInternalState_from_Encode() throws CharacterCodingException {
+        CharsetEncoder newEncoder = cs.newEncoder();
+        
+        //Encode -> Reset
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            newEncoder.encode(in);
+            newEncoder.reset();
+        }
+        
+        // Encode -> encoding
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            newEncoder.encode(in);
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            try {
+                newEncoder.encode(in, out, false);
+                fail("Should throw IllegalStateException");
+            } catch (IllegalStateException e) {
+                // expected
+            }
+        }
+        
+        //Encode -> Encoding_end
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            newEncoder.encode(in);
+            ByteBuffer out = ByteBuffer.allocate(0x10);
+            newEncoder.encode(in, out, true);
+        }
+
+        //Encode -> Flushed
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            ByteBuffer out = newEncoder.encode(in);
+            newEncoder.flush(out);
+        }
+        
+        //Encode - > encode
+        {
+            CharBuffer in = CharBuffer.wrap("A");
+            newEncoder.encode(in);
+            in = CharBuffer.wrap("BC");
+            newEncoder.encode(in);
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.java
new file mode 100644
index 0000000..a45938f
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.java
@@ -0,0 +1,53 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.IOException;
+import java.nio.charset.CharacterCodingException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Test CharacterCodingException
+ */
+public class CharacterCodingExceptionTest extends TestCase {
+
+	public void testConstructor() {
+		CharacterCodingException ex = new CharacterCodingException();
+		assertTrue(ex instanceof IOException);
+		assertNull(ex.getCause());
+		assertNull(ex.getMessage());
+	}
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new CharacterCodingException());
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+        SerializationTest.verifyGolden(this, new CharacterCodingException());
+
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
new file mode 100644
index 0000000..4ed4ab9
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
@@ -0,0 +1,280 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.IOException;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderMalfunctionError;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+public class CharsetDecoderTest extends TestCase {
+
+    /**
+	 * @tests java.nio.charset.CharsetDecoder.CharsetDecoder(Charset, float,
+	 *        float)
+	 */
+	public void test_ConstructorLjava_nio_charset_CharsetFF() {
+		// Regression for HARMONY-142
+		try {
+			Charset cs = Charset.forName("UTF-8"); //$NON-NLS-1$
+			new MockCharsetDecoderForHarmony142(cs, 1.1f, 1);
+			fail("Assert 0: Should throw IllegalArgumentException."); //$NON-NLS-1$
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * MockCharsetDecoderForHarmony142: for constructor test
+	 */
+	static class MockCharsetDecoderForHarmony142 extends CharsetDecoder {
+		protected MockCharsetDecoderForHarmony142(Charset cs,
+				float averageBytesPerChar, float maxBytesPerChar) {
+			super(cs, averageBytesPerChar, maxBytesPerChar);
+		}
+
+		protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+			return null;
+		}
+	}
+ 
+	/**
+	 * @tests java.nio.charset.CharsetDecoder#decode(java.nio.ByteBuffer)
+	 */
+	public void test_decode() throws CharacterCodingException {
+		// Regression for HARMONY-33
+//		ByteBuffer bb = ByteBuffer.allocate(1);
+//		bb.put(0, (byte) 77);
+//		CharsetDecoder decoder = Charset.forName("UTF-16").newDecoder();
+//		decoder.onMalformedInput(CodingErrorAction.REPLACE);
+//		decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+//		decoder.decode(bb);
+
+		// Regression for HARMONY-67
+//		byte[] b = new byte[] { (byte) 1 };
+//		ByteBuffer buf = ByteBuffer.wrap(b);
+//		CharBuffer charbuf = Charset.forName("UTF-16").decode(buf);
+//		assertEquals("Assert 0: charset UTF-16", 1, charbuf.length());
+//
+//		charbuf = Charset.forName("UTF-16BE").decode(buf);
+//		assertEquals("Assert 1: charset UTF-16BE", 0, charbuf.length());
+//
+//		charbuf = Charset.forName("UTF-16LE").decode(buf);
+//		assertEquals("Assert 2: charset UTF16LE", 0, charbuf.length());
+		
+		// Regression for HARMONY-99
+		CharsetDecoder decoder2 = Charset.forName("UTF-16").newDecoder();
+		decoder2.onMalformedInput(CodingErrorAction.REPORT);
+		decoder2.onUnmappableCharacter(CodingErrorAction.REPORT);
+		ByteBuffer in = ByteBuffer.wrap(new byte[] { 109, 97, 109 });
+		try {
+			decoder2.decode(in);
+			fail("Assert 3: MalformedInputException should have thrown");
+		} catch (MalformedInputException e) {
+			//expected
+		} 
+	}
+	
+    /*
+     * Test malfunction decode(ByteBuffer)
+     */
+    public void test_decodeLjava_nio_ByteBuffer() throws Exception {
+		MockMalfunctionCharset cs1 = new MockMalfunctionCharset(
+				"Harmony-124-1", null); //$NON-NLS-1$
+		try {
+			cs1.newDecoder().onMalformedInput(CodingErrorAction.REPLACE)
+					.onUnmappableCharacter(CodingErrorAction.REPLACE).decode(
+							ByteBuffer.wrap(new byte[] { 0x00, 0x11 }));
+			fail("Assert 0: should throw CoderMalfunctionError");  // NON-NLS-1$
+		} catch (CoderMalfunctionError e) {
+			// expected
+		}
+
+		MockMalfunctionCharset cs2 = new MockMalfunctionCharset(
+				"Harmony-124-2", null); //$NON-NLS-1$
+		try {
+			cs2.decode(ByteBuffer.wrap(new byte[] { 0x00, 0x11 }));
+			fail("Assert 1: Charset.decode should throw CoderMalfunctionError");  // NON-NLS-1
+		} catch (CoderMalfunctionError e) {
+			// expected
+		}
+	}
+    
+	/*
+	 * Mock charset class with malfunction decode & encode.
+	 */
+	static final class MockMalfunctionCharset extends Charset {
+
+		public MockMalfunctionCharset(String canonicalName, String[] aliases) {
+			super(canonicalName, aliases);
+		}
+
+		public boolean contains(Charset cs) {
+			return false;
+		}
+
+		public CharsetDecoder newDecoder() {
+			return new MockMalfunctionDecoder(this);
+		}
+
+		public CharsetEncoder newEncoder() {
+			return new MockMalfunctionEncoder(this);
+		}
+	}
+
+	/*
+	 * Mock decoder. decodeLoop always throws unexpected exception.
+	 */
+	static class MockMalfunctionDecoder extends java.nio.charset.CharsetDecoder {
+
+		public MockMalfunctionDecoder(Charset cs) {
+			super(cs, 1, 10);
+		}
+
+		protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+			throw new BufferOverflowException();
+		}
+	}
+
+	/*
+	 * Mock encoder. encodeLoop always throws unexpected exception.
+	 */
+	static class MockMalfunctionEncoder extends java.nio.charset.CharsetEncoder {
+
+		public MockMalfunctionEncoder(Charset cs) {
+			super(cs, 1, 3, new byte[] { (byte) '?' });
+		}
+
+		protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+			throw new BufferOverflowException();
+		}
+	} 
+	
+	/*
+	 * Test the method decode(ByteBuffer) .
+	 */
+	public void testDecodeLjava_nio_ByteBuffer_ReplaceOverflow()
+			throws Exception {
+		String replaceString = "a";
+		Charset cs = Charset.forName("UTF-8");
+		MockMalformedDecoder decoder = new MockMalformedDecoder(cs);
+		decoder.onMalformedInput(CodingErrorAction.REPLACE);
+		decoder.replaceWith(replaceString);
+		CharBuffer out = CharBuffer.allocate(1);
+		// MockMalformedDecoder treats the second byte '0x38' as malformed,
+		// but "out" doesn't have enough space for replace string.
+		ByteBuffer in = ByteBuffer.wrap(new byte[] { 0x45, 0x38, 0x45, 0x45 });
+		CoderResult result = decoder.decode(in, out, false);
+		assertTrue(result.isOverflow());
+
+		// allocate enough space for "out"
+		out = CharBuffer.allocate(10);
+		// replace string should be put into "out" firstly,
+		// and then decode "in".
+		result = decoder.decode(in, out, true);
+		out.flip();
+		assertTrue(result.isUnderflow());
+		assertEquals("bb", out.toString());
+	}
+
+	/*
+	 * Mock decoder. It treats byte whose value is less than "0x40" as
+	 * malformed.
+	 */
+	static class MockMalformedDecoder extends java.nio.charset.CharsetDecoder {
+
+		public MockMalformedDecoder(Charset cs) {
+			super(cs, 1, 10);
+		}
+
+		/*
+		 * It treats byte whose value is less than "0x40" as malformed.
+		 * Otherwise, it's decoded as 'b'.
+		 */
+		protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+			while (in.hasRemaining()) {
+				byte b = in.get();
+				if (b < 0x40) {
+					return CoderResult.malformedForLength(1);
+				}
+				if (!out.hasRemaining()) {
+					return CoderResult.OVERFLOW;
+				}
+				out.put((char) 'b');
+			}
+			return CoderResult.UNDERFLOW;
+		}
+	}
+
+
+    public void testInvalidDecoding() throws IOException {
+
+        byte[][] invalidSequences = new byte[][] {
+            // overlong NULL
+            { (byte) 0xC0, (byte) 0x80 },
+            // overlong ascii 'A'
+            { (byte) 0xC0, (byte) 0xC1 },
+            // overlong "/../"
+            { (byte) 0x2F, (byte) 0xC0, (byte) 0xAE, (byte) 0x2E, (byte) 0x2F },
+            // Invalid encoding 2r11111000 (sequence too long)
+            { (byte) 0xF8 },
+            // Invalid encoding 2r10000000 (sequence too short)
+            { (byte) 0x80 }
+        };
+
+        CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
+        decoder.onMalformedInput(CodingErrorAction.REPORT);
+
+        /*
+         * When bytebuffer has a backing array...
+         */
+        for (byte[] bytes : invalidSequences) {
+            try {
+                decoder.decode(ByteBuffer.wrap(bytes));
+                fail("No exception thrown on " + Arrays.toString(bytes));
+            } catch (MalformedInputException e) {
+                // expected
+            }
+        }
+
+        /*
+         * When bytebuffer has _not_ got a backing array...
+         */
+        for (byte[] bytes : invalidSequences) {
+            try {
+                ByteBuffer bb = ByteBuffer.allocateDirect(8);
+                bb.put(bytes).flip();
+                decoder.decode(bb);
+                fail("No exception thrown on " + Arrays.toString(bytes));
+            } catch (MalformedInputException e) {
+                // expected
+            }
+        }
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
new file mode 100644
index 0000000..dd514da
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
@@ -0,0 +1,202 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.IOException;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderMalfunctionError;
+import java.nio.charset.CoderResult;
+
+import junit.framework.TestCase;
+
+public class CharsetEncoderTest extends TestCase {
+
+    /**
+     * @tests java.nio.charset.CharsetEncoder.CharsetEncoder(
+     *        java.nio.charset.Charset, float, float)
+     */
+    public void test_ConstructorLjava_nio_charset_CharsetFF() {
+        // Regression for HARMONY-141
+        try {
+            Charset cs = Charset.forName("UTF-8"); //$NON-NLS-1$
+            new MockCharsetEncoderForHarmony141(cs, 1.1f, 1);
+            fail("Assert 0: Should throw IllegalArgumentException."); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            Charset cs = Charset.forName("ISO8859-1"); //$NON-NLS-1$
+            new MockCharsetEncoderForHarmony141(cs, 1.1f, 1,
+                    new byte[] { 0x1a });
+            fail("Assert 1: Should throw IllegalArgumentException."); //$NON-NLS-1$
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    /**
+     * @tests java.nio.charset.CharsetEncoder.CharsetEncoder(
+     *        java.nio.charset.Charset, float, float)
+     */
+    public void test_ConstructorLjava_nio_charset_CharsetNull() {
+        // Regression for HARMONY-491
+        CharsetEncoder ech = new MockCharsetEncoderForHarmony491(null, 1, 1);
+        assertNull(ech.charset());
+    }
+
+    /**
+     * Helper for constructor tests
+     */
+
+    public static class MockCharsetEncoderForHarmony141 extends CharsetEncoder {
+
+        protected MockCharsetEncoderForHarmony141(Charset cs,
+                float averageBytesPerChar, float maxBytesPerChar) {
+            super(cs, averageBytesPerChar, maxBytesPerChar);
+        }
+
+        public MockCharsetEncoderForHarmony141(Charset cs,
+                float averageBytesPerChar, float maxBytesPerChar,
+                byte[] replacement) {
+            super(cs, averageBytesPerChar, maxBytesPerChar, replacement);
+        }
+
+        protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+            return null;
+        }
+    }
+
+    public static class MockCharsetEncoderForHarmony491 extends CharsetEncoder {
+
+        public MockCharsetEncoderForHarmony491(Charset arg0, float arg1,
+                float arg2) {
+            super(arg0, arg1, arg2);
+        }
+
+        protected CoderResult encodeLoop(CharBuffer arg0, ByteBuffer arg1) {
+            return null;
+        }
+
+        public boolean isLegalReplacement(byte[] arg0) {
+            return true;
+        }
+    }
+
+    /*
+     * Test malfunction encode(CharBuffer)
+     */
+    public void test_EncodeLjava_nio_CharBuffer() throws Exception {
+        MockMalfunctionCharset cs = new MockMalfunctionCharset("mock", null);
+        try {
+            cs.encode(CharBuffer.wrap("AB"));
+            fail("should throw CoderMalfunctionError");// NON-NLS-1$
+        } catch (CoderMalfunctionError e) {
+            // expected
+        }
+    }
+
+    /*
+     * Mock charset class with malfunction decode & encode.
+     */
+    static final class MockMalfunctionCharset extends Charset {
+
+        public MockMalfunctionCharset(String canonicalName, String[] aliases) {
+            super(canonicalName, aliases);
+        }
+
+        public boolean contains(Charset cs) {
+            return false;
+        }
+
+        public CharsetDecoder newDecoder() {
+            return Charset.forName("UTF-8").newDecoder();
+        }
+
+        public CharsetEncoder newEncoder() {
+            return new MockMalfunctionEncoder(this);
+        }
+    }
+
+    /*
+     * Mock encoder. encodeLoop always throws unexpected exception.
+     */
+    static class MockMalfunctionEncoder extends java.nio.charset.CharsetEncoder {
+
+        public MockMalfunctionEncoder(Charset cs) {
+            super(cs, 1, 3, new byte[] { (byte) '?' });
+        }
+
+        protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+            throw new BufferOverflowException();
+        }
+    }
+
+    /*
+     * Test reserve bytes encode(CharBuffer,ByteBuffer,boolean)
+     */
+    public void test_EncodeLjava_nio_CharBufferLjava_nio_ByteBufferB() throws Exception {
+        Charset utf8 = Charset.forName("utf-8");
+        CharsetEncoder encoder = utf8.newEncoder();
+        CharBuffer in1 = CharBuffer.wrap("\ud800");
+        CharBuffer in2 = CharBuffer.wrap("\udc00");
+        ByteBuffer out = ByteBuffer.allocate(4);
+        encoder.reset();
+
+        // If we supply just the high surrogate...
+        CoderResult result = encoder.encode(in1, out, false);
+        // ...we're not done...
+        assertTrue(result.isUnderflow());
+        assertEquals(4, out.remaining());
+        // ...but if we then supply the low surrogate...
+        result = encoder.encode(in2, out, true);
+        // ...we're done. Note that the RI loses its state in
+        // between the two characters, so it can't do this.
+        assertEquals(0, out.remaining());
+
+        // See what we got in the output buffer by decoding and checking that we
+        // get back the same surrogate pair.
+        out.flip();
+        CharBuffer chars = utf8.newDecoder().decode(out);
+        assertEquals(0xd800, chars.get(0));
+        assertEquals(0xdc00, chars.get(1));
+    }
+
+    /**
+     * @tests {@link java.nio.charset.Charset#encode(java.nio.CharBuffer)
+     */
+    public void testUtf8Encoding() throws IOException {
+        byte[] orig = new byte[] { (byte) 0xed, (byte) 0xa0,
+                (byte) 0x80 };
+        String s = new String(orig, "UTF-8");
+        assertEquals(1, s.length());
+        assertEquals(55296, s.charAt(0));
+        Charset.forName("UTF-8").encode(CharBuffer.wrap(s));
+//        ByteBuffer buf = <result>
+//        for (byte o : orig) {
+//            byte b = 0;
+//            buf.get(b);
+//            assertEquals(o, b);
+//        }
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java
new file mode 100644
index 0000000..134bea6
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java
@@ -0,0 +1,245 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.IllegalCharsetNameException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+public class CharsetTest extends TestCase {
+
+	// Will contain names of charsets registered with IANA
+	Set knownRegisteredCharsets = new HashSet();
+
+	// Will contain names of charsets not known to be registered with IANA
+	Set unknownRegisteredCharsets = new HashSet();
+
+	/**
+	 * JUnit set-up method
+	 */
+	public void setUp() {
+		// Populate the known charset vars
+		Set names = Charset.availableCharsets().keySet();
+		for (Iterator nameItr = names.iterator(); nameItr.hasNext();) {
+			String name = (String) nameItr.next();
+			if (name.toLowerCase(Locale.ROOT).startsWith("x-"))
+				unknownRegisteredCharsets.add(name);
+			else
+				knownRegisteredCharsets.add(name);
+		}
+	}
+
+	/**
+	 * @tests java.nio.charset.Charset#isRegistered()
+	 */
+	public void test_isRegistered() {
+		// Regression for HARMONY-45
+		for (Iterator nameItr = knownRegisteredCharsets.iterator(); nameItr.hasNext();) {
+			String name = (String) nameItr.next();
+			assertTrue("Assert 0: isRegistered() failed for " + name,
+					Charset.forName(name).isRegistered());
+		}
+		for (Iterator nameItr = unknownRegisteredCharsets.iterator(); nameItr.hasNext();) {
+			String name = (String) nameItr.next();
+			assertFalse("Assert 0: isRegistered() failed for " + name,
+					Charset.forName(name).isRegistered());
+		}
+	}
+
+	/**
+	 * @tests java.nio.charset.Charset#isSupported(String)
+	 */
+	public void testIsSupported_EmptyString() {
+		// Regression for HARMONY-113
+		try {
+			Charset.isSupported("");
+			fail("Assert 0: Should throw IllegalCharsetNameException");
+		} catch (IllegalCharsetNameException e) {
+			// Expected
+		}
+	}
+
+    public void test_defaultCharset() {
+        assertEquals("UTF-8", Charset.defaultCharset().name());
+    }
+
+	public void test_forNameLjava_lang_String() {
+		/*
+		 * invoke forName two times with the same canonical name, it
+		 * should return the same reference.
+		 */
+		Charset cs1 = Charset.forName("UTF-8");
+		Charset cs2 = Charset.forName("UTF-8");
+		assertSame(cs1, cs2);
+
+		/*
+		 * test forName: invoke forName two times for the same Charset using
+		 * canonical name and alias, it should return the same reference.
+		 */
+		Charset cs3 = Charset.forName("ASCII");
+		Charset cs4 = Charset.forName("US-ASCII");
+		assertSame(cs3, cs4);
+	}
+
+	/*
+     * test cached decoder
+     */
+//    public void test_DecodeLjava_nio_ByteBuffer() throws Exception{
+//            MockCharsetForDecoder cs1 = new MockCharsetForDecoder("CachedCharset",null);
+//            MockCharsetForDecoder cs2 = new MockCharsetForDecoder("CachedCharset",null);
+//            ByteBuffer in = ByteBuffer.wrap(new byte[]{0x00});
+//            cs1.decode(in);
+//            in.flip();
+//            cs2.decode(in);
+//            in.flip();
+//    }
+    /*
+     * Mock Charset for cached decoder test
+     */
+    static class MockCharsetForDecoder extends Charset{
+
+            public MockCharsetForDecoder(String canonicalName, String[] aliases){
+                    super(canonicalName, aliases);
+            }
+
+            public boolean contains(Charset charset) {
+                    return false;
+            }
+
+            public CharsetEncoder newEncoder() {
+                    return null;
+            }
+
+            public CharsetDecoder newDecoder() {
+                    return new MockCachedDecoder(this);
+            }
+
+
+    }
+    /*
+     * Mock decoder. Only one caller is permitted.
+     */
+    static class MockCachedDecoder extends CharsetDecoder {
+            static MockCachedDecoder caller = null;
+
+            public MockCachedDecoder(Charset cs) {
+                    super(cs, 1, 10);
+            }
+
+            /*
+             * Only one caller is permitted.
+             * If there's another caller, throw RuntimeException.
+             */
+            protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+                    if(null == caller){
+                            caller = this;
+                    }else{
+                            if(caller != this){
+                                // Another instance
+                            	fail("should use the same instance");
+                            }
+                    }
+                    return CoderResult.UNDERFLOW;
+            }
+    }
+
+    /*
+     * test cached encoder
+     */
+//    public void test_EncodeLjava_nio_CharBuffer() throws Exception {
+//            MockCharsetForEncoder cs1 = new MockCharsetForEncoder("CachedCharset", null);
+//            MockCharsetForEncoder cs2 = new MockCharsetForEncoder("CachedCharset", null);
+//            CharBuffer in = CharBuffer.wrap("A");
+//            cs1.encode(in);
+//            in.flip();
+//            cs2.encode(in);
+//    }
+
+    /*
+     * Mock Charset for cached encoder test
+     */
+    static class MockCharsetForEncoder extends Charset {
+
+            public MockCharsetForEncoder(String canonicalName, String[] aliases) {
+                    super(canonicalName, aliases);
+            }
+
+            public boolean contains(Charset charset) {
+                    return false;
+            }
+
+            public CharsetDecoder newDecoder() {
+                    return new MockDecoderForEncoder(this);
+            }
+
+            public CharsetEncoder newEncoder() {
+                    return new MockCachedEncoder(this);
+            }
+    }
+
+    /*
+     * Mock encoder. Only one caller is permitted.
+     */
+    static class MockCachedEncoder extends CharsetEncoder {
+            static MockCachedEncoder caller = null;
+
+            public MockCachedEncoder(Charset cs) {
+                    super(cs, 1, 10);
+            }
+
+            /*
+             * Only one caller is permitted.
+             */
+            protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+                    if (null == caller) {
+                            caller = this;
+                    } else {
+                            if (caller != this) {
+                                    // Another instance
+                                    fail("should use the same instance");
+                            }
+                    }
+                    return CoderResult.UNDERFLOW;
+            }
+    }
+
+    /*
+     * Mock decoder for MockCachedEncoder.
+     */
+    static class MockDecoderForEncoder extends CharsetDecoder {
+            public MockDecoderForEncoder(Charset cs) {
+                    super(cs, 1, 10);
+            }
+
+            protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+                    in.position(in.limit());
+                    return CoderResult.UNDERFLOW;
+            }
+    }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.java
new file mode 100644
index 0000000..8e6318f
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.java
@@ -0,0 +1,62 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.nio.charset.CoderMalfunctionError;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Test java.nio.CoderMalfunctionError.
+ */
+public class CoderMalfunctionErrorTest extends TestCase {
+
+	/*
+	 * Test constructor with normal param.
+	 */
+	public void testConstructor_Normal() {
+		Exception ex = new Exception();
+		CoderMalfunctionError e = new CoderMalfunctionError(ex);
+		assertSame(ex, e.getCause());
+	}
+
+	/*
+	 * Test constructor with null param.
+	 */
+	public void testConstructor_Null() {
+		CoderMalfunctionError e = new CoderMalfunctionError(null);
+		assertNull(e.getCause());
+	}
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new CoderMalfunctionError(null));
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+        SerializationTest.verifyGolden(this, new CoderMalfunctionError(null));
+
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.java
new file mode 100644
index 0000000..a514aef
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.java
@@ -0,0 +1,94 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.Serializable;
+import java.nio.charset.IllegalCharsetNameException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class IllegalCharsetNameException.
+ */
+public class IllegalCharsetNameExceptionTest extends TestCase {
+
+	public void testConstructor() {
+		IllegalCharsetNameException ex = new IllegalCharsetNameException(
+				"impossible");
+		assertTrue(ex instanceof IllegalArgumentException);
+		assertNull(ex.getCause());
+		assertEquals(ex.getCharsetName(), "impossible");
+		assertTrue(ex.getMessage().indexOf("impossible") != -1);
+
+		ex = new IllegalCharsetNameException("ascii");
+		assertNull(ex.getCause());
+		assertEquals(ex.getCharsetName(), "ascii");
+		assertTrue(ex.getMessage().indexOf("ascii") != -1);
+
+		ex = new IllegalCharsetNameException("");
+		assertNull(ex.getCause());
+		assertEquals(ex.getCharsetName(), "");
+		ex.getMessage();
+
+		ex = new IllegalCharsetNameException(null);
+		assertNull(ex.getCause());
+		assertNull(ex.getCharsetName());
+		assertTrue(ex.getMessage().indexOf("null") != -1);
+
+	}
+
+    // comparator for IllegalCharsetNameException objects
+    private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+        public void assertDeserialized(Serializable initial,
+                Serializable deserialized) {
+
+            // FIXME?: getMessage() returns more helpful string but
+            // this leads to incompatible message in serial form
+            //
+            // do common checks for all throwable objects
+            // SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+            //        deserialized);
+
+            IllegalCharsetNameException initEx = (IllegalCharsetNameException) initial;
+            IllegalCharsetNameException desrEx = (IllegalCharsetNameException) deserialized;
+
+            assertEquals("CharsetName", initEx.getCharsetName(), desrEx
+                    .getCharsetName());
+        }
+    };
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new IllegalCharsetNameException(
+                "charsetName"), COMPARATOR);
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new IllegalCharsetNameException(
+                "charsetName"), COMPARATOR);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.java
new file mode 100644
index 0000000..f482d9d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.java
@@ -0,0 +1,85 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.Serializable;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.MalformedInputException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class MalformedInputException.
+ */
+public class MalformedInputExceptionTest extends TestCase {
+
+	public void testConstructor() {
+		MalformedInputException ex = new MalformedInputException(3);
+		assertTrue(ex instanceof CharacterCodingException);
+		assertNull(ex.getCause());
+		assertEquals(ex.getInputLength(), 3);
+		assertTrue(ex.getMessage().indexOf("3") != -1);
+
+		ex = new MalformedInputException(-3);
+		assertNull(ex.getCause());
+		assertEquals(ex.getInputLength(), -3);
+		assertTrue(ex.getMessage().indexOf("-3") != -1);
+
+		ex = new MalformedInputException(0);
+		assertNull(ex.getCause());
+		assertEquals(ex.getInputLength(), 0);
+		assertTrue(ex.getMessage().indexOf("0") != -1);
+	}
+
+    // comparator for MalformedInputException objects
+    private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+        public void assertDeserialized(Serializable initial,
+                Serializable deserialized) {
+
+            // do common checks for all throwable objects
+            SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+                    deserialized);
+
+            MalformedInputException initEx = (MalformedInputException) initial;
+            MalformedInputException desrEx = (MalformedInputException) deserialized;
+
+            assertEquals("InputLength", initEx.getInputLength(), desrEx
+                    .getInputLength());
+        }
+    };
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new MalformedInputException(11),
+                COMPARATOR);
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new MalformedInputException(11),
+                COMPARATOR);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.java
new file mode 100644
index 0000000..a6cf6a6
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.java
@@ -0,0 +1,86 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.Serializable;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class UnmappableCharacterException.
+ */
+public class UnmappableCharacterExceptionTest extends TestCase {
+
+	public void testConstructor() {
+		UnmappableCharacterException ex = new UnmappableCharacterException(3);
+		assertTrue(ex instanceof CharacterCodingException);
+		assertNull(ex.getCause());
+		assertEquals(ex.getInputLength(), 3);
+		assertTrue(ex.getMessage().indexOf("3") != -1);
+
+		ex = new UnmappableCharacterException(-3);
+		assertNull(ex.getCause());
+		assertEquals(ex.getInputLength(), -3);
+		assertTrue(ex.getMessage().indexOf("-3") != -1);
+
+		ex = new UnmappableCharacterException(0);
+		assertNull(ex.getCause());
+		assertEquals(ex.getInputLength(), 0);
+		assertTrue(ex.getMessage().indexOf("0") != -1);
+
+	}
+
+    // comparator for UnmappableCharacterException objects
+    private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+        public void assertDeserialized(Serializable initial,
+                Serializable deserialized) {
+
+            // do common checks for all throwable objects
+            SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+                    deserialized);
+
+            UnmappableCharacterException initEx = (UnmappableCharacterException) initial;
+            UnmappableCharacterException desrEx = (UnmappableCharacterException) deserialized;
+
+            assertEquals("InputLength", initEx.getInputLength(), desrEx
+                    .getInputLength());
+        }
+    };
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new UnmappableCharacterException(11),
+                COMPARATOR);
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new UnmappableCharacterException(
+                11), COMPARATOR);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.java
new file mode 100644
index 0000000..57ea31c
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.java
@@ -0,0 +1,93 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio_char.tests.java.nio.charset;
+
+import java.io.Serializable;
+import java.nio.charset.UnsupportedCharsetException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class UnsupportedCharsetException.
+ */
+public class UnsupportedCharsetExceptionTest extends TestCase {
+
+	public void testConstructor() {
+		UnsupportedCharsetException ex = new UnsupportedCharsetException(
+				"impossible");
+		assertTrue(ex instanceof IllegalArgumentException);
+		assertNull(ex.getCause());
+		assertEquals(ex.getCharsetName(), "impossible");
+		assertTrue(ex.getMessage().indexOf("impossible") != -1);
+
+		ex = new UnsupportedCharsetException("ascii");
+		assertNull(ex.getCause());
+		assertEquals(ex.getCharsetName(), "ascii");
+		assertTrue(ex.getMessage().indexOf("ascii") != -1);
+
+		ex = new UnsupportedCharsetException("");
+		assertNull(ex.getCause());
+		assertEquals(ex.getCharsetName(), "");
+		ex.getMessage();
+
+		ex = new UnsupportedCharsetException(null);
+		assertNull(ex.getCause());
+		assertNull(ex.getCharsetName());
+		assertTrue(ex.getMessage().indexOf("null") != -1);
+	}
+
+    // comparator for UnsupportedCharsetException objects
+    private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+        public void assertDeserialized(Serializable initial,
+                Serializable deserialized) {
+
+            // FIXME?: getMessage() returns more helpful string but
+            // this leads to incompatible message in serial form
+            //
+            // do common checks for all throwable objects
+            // SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+            //        deserialized);
+
+            UnsupportedCharsetException initEx = (UnsupportedCharsetException) initial;
+            UnsupportedCharsetException desrEx = (UnsupportedCharsetException) deserialized;
+
+            assertEquals("CharsetName", initEx.getCharsetName(), desrEx
+                    .getCharsetName());
+        }
+    };
+
+    /**
+     * @tests serialization/deserialization compatibility.
+     */
+    public void testSerializationSelf() throws Exception {
+
+        SerializationTest.verifySelf(new UnsupportedCharsetException(
+                "charsetName"), COMPARATOR);
+    }
+
+    /**
+     * @tests serialization/deserialization compatibility with RI.
+     */
+    public void testSerializationCompatibility() throws Exception {
+
+        SerializationTest.verifyGolden(this, new UnsupportedCharsetException(
+                "charsetName"), COMPARATOR);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalArithmeticTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalArithmeticTest.java
new file mode 100644
index 0000000..ba71e2c
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalArithmeticTest.java
@@ -0,0 +1,1623 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+import junit.framework.TestCase;
+
+/**
+ * Class:  java.math.BigDecimal
+ * Methods: add, subtract, multiply, divide 
+ */
+public class BigDecimalArithmeticTest extends TestCase {
+    /**
+     * Add two numbers of equal positive scales
+     */
+    public void testAddEqualScalePosPos() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 10;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        String c = "123121247898748373566323807282924555312937.1991359555";
+        int cScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.add(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Add two numbers of equal positive scales using MathContext
+     */
+    public void testAddMathContextEqualScalePosPos() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 10;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        String c = "1.2313E+41";
+        int cScale = -37;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        MathContext mc = new MathContext(5, RoundingMode.UP);
+        BigDecimal result = aNumber.add(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Add two numbers of equal negative scales
+     */
+    public void testAddEqualScaleNegNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -10;
+        String b = "747233429293018787918347987234564568";
+        int bScale = -10;
+        String c = "1.231212478987483735663238072829245553129371991359555E+61";
+        int cScale = -10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.add(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Add two numbers of equal negative scales using MathContext
+     */
+    public void testAddMathContextEqualScaleNegNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -10;
+        String b = "747233429293018787918347987234564568";
+        int bScale = -10;
+        String c = "1.2312E+61";
+        int cScale = -57;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        MathContext mc = new MathContext(5, RoundingMode.FLOOR);
+        BigDecimal result = aNumber.add(bNumber, mc);
+        assertEquals("incorrect value ", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Add two numbers of different scales; the first is positive
+     */
+    public void testAddDiffScalePosNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = -10;
+        String c = "7472334294161400358170962860775454459810457634.781384756794987";
+        int cScale = 15;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.add(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Add two numbers of different scales using MathContext; the first is positive
+     */
+    public void testAddMathContextDiffScalePosNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = -10;
+        String c = "7.47233429416141E+45";
+        int cScale = -31;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        MathContext mc = new MathContext(15, RoundingMode.CEILING);
+        BigDecimal result = aNumber.add(bNumber, mc);
+        assertEquals("incorrect value", c, c.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Add two numbers of different scales; the first is negative
+     */
+    public void testAddDiffScaleNegPos() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        String c = "1231212478987482988429808779810457634781459480137916301878791834798.7234564568";
+        int cScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.add(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Add two zeroes of different scales; the first is negative
+     */
+    public void testAddDiffScaleZeroZero() {
+        String a = "0";
+        int aScale = -15;
+        String b = "0";
+        int bScale = 10;
+        String c = "0E-10";
+        int cScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.add(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Subtract two numbers of equal positive scales
+     */
+    public void testSubtractEqualScalePosPos() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 10;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        String c = "123121247898748224119637948679166971643339.7522230419";
+        int cScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.subtract(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Subtract two numbers of equal positive scales using MathContext
+     */
+    public void testSubtractMathContextEqualScalePosPos() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 10;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        String c = "1.23121247898749E+41";
+        int cScale = -27;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        MathContext mc = new MathContext(15, RoundingMode.CEILING);
+        BigDecimal result = aNumber.subtract(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Subtract two numbers of equal negative scales
+     */
+    public void testSubtractEqualScaleNegNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -10;
+        String b = "747233429293018787918347987234564568";
+        int bScale = -10;
+        String c = "1.231212478987482241196379486791669716433397522230419E+61";
+        int cScale = -10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.subtract(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Subtract two numbers of different scales; the first is positive
+     */
+    public void testSubtractDiffScalePosNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = -10;
+        String c = "-7472334291698975400195996883915836900189542365.218615243205013";
+        int cScale = 15;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.subtract(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Subtract two numbers of different scales using MathContext;
+     *  the first is positive
+     */
+    public void testSubtractMathContextDiffScalePosNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = -10;
+        String c = "-7.4723342916989754E+45";
+        int cScale = -29;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        MathContext mc = new MathContext(17, RoundingMode.DOWN);
+        BigDecimal result = aNumber.subtract(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Subtract two numbers of different scales; the first is negative
+     */
+    public void testSubtractDiffScaleNegPos() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        String c = "1231212478987482988429808779810457634781310033452057698121208165201.2765435432";
+        int cScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.subtract(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Subtract two numbers of different scales using MathContext;
+     *  the first is negative
+     */
+    public void testSubtractMathContextDiffScaleNegPos() {
+        String a = "986798656676789766678767876078779810457634781384756794987";
+        int aScale = -15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 40;
+        String c = "9.867986566767897666787678760787798104576347813847567949870000000000000E+71";
+        int cScale = -2;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        MathContext mc = new MathContext(70, RoundingMode.HALF_DOWN);
+        BigDecimal result = aNumber.subtract(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Multiply two numbers of positive scales
+     */
+    public void testMultiplyScalePosPos() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        String c = "92000312286217574978643009574114545567010139156902666284589309.1880727173060570190220616";
+        int cScale = 25;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.multiply(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Multiply two numbers of positive scales using MathContext
+     */
+    public void testMultiplyMathContextScalePosPos() {
+        String a = "97665696756578755423325476545428779810457634781384756794987";
+        int aScale = -25;
+        String b = "87656965586786097685674786576598865";
+        int bScale = 10;
+        String c = "8.561078619600910561431314228543672720908E+108";
+        int cScale = -69;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        MathContext mc = new MathContext(40, RoundingMode.HALF_DOWN);
+        BigDecimal result = aNumber.multiply(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Multiply two numbers of negative scales
+     */
+    public void testMultiplyEqualScaleNegNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = -10;
+        String c = "9.20003122862175749786430095741145455670101391569026662845893091880727173060570190220616E+111";
+        int cScale = -25;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.multiply(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Multiply two numbers of different scales
+     */
+    public void testMultiplyDiffScalePosNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 10;
+        String b = "747233429293018787918347987234564568";
+        int bScale = -10;
+        String c = "920003122862175749786430095741145455670101391569026662845893091880727173060570190220616";
+        int cScale = 0;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.multiply(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Multiply two numbers of different scales using MathContext
+     */
+    public void testMultiplyMathContextDiffScalePosNeg() {
+        String a = "987667796597975765768768767866756808779810457634781384756794987";
+        int aScale = 100;
+        String b = "747233429293018787918347987234564568";
+        int bScale = -70;
+        String c = "7.3801839465418518653942222612429081498248509257207477E+68";
+        int cScale = -16;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        MathContext mc = new MathContext(53, RoundingMode.HALF_UP);
+        BigDecimal result = aNumber.multiply(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Multiply two numbers of different scales
+     */
+    public void testMultiplyDiffScaleNegPos() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        String c = "9.20003122862175749786430095741145455670101391569026662845893091880727173060570190220616E+91";
+        int cScale = -5;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.multiply(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Multiply two numbers of different scales using MathContext
+     */
+    public void testMultiplyMathContextDiffScaleNegPos() {
+        String a = "488757458676796558668876576576579097029810457634781384756794987";
+        int aScale = -63;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 63;
+        String c = "3.6521591193960361339707130098174381429788164316E+98";
+        int cScale = -52;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        MathContext mc = new MathContext(47, RoundingMode.HALF_UP);
+        BigDecimal result = aNumber.multiply(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * pow(int)
+     */
+    public void testPow() {
+        String a = "123121247898748298842980";
+        int aScale = 10;
+        int exp = 10;
+        String c = "8004424019039195734129783677098845174704975003788210729597" +
+                   "4875206425711159855030832837132149513512555214958035390490" +
+                   "798520842025826.594316163502809818340013610490541783276343" +
+                   "6514490899700151256484355936102754469438371850240000000000";
+        int cScale = 100;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.pow(exp);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * pow(0)
+     */
+    public void testPow0() {
+        String a = "123121247898748298842980";
+        int aScale = 10;
+        int exp = 0;
+        String c = "1";
+        int cScale = 0;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.pow(exp);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * ZERO.pow(0)
+     */
+    public void testZeroPow0() {
+        String c = "1";
+        int cScale = 0;
+        BigDecimal result = BigDecimal.ZERO.pow(0);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * pow(int, MathContext)
+     */
+    public void testPowMathContext() {
+        String a = "123121247898748298842980";
+        int aScale = 10;
+        int exp = 10;
+        String c = "8.0044E+130";
+        int cScale = -126;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        MathContext mc = new MathContext(5, RoundingMode.HALF_UP);
+        BigDecimal result = aNumber.pow(exp, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", cScale, result.scale());
+    }
+
+    /**
+     * Divide by zero
+     */
+    public void testDivideByZero() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 15;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = BigDecimal.valueOf(0L);
+        try {
+            aNumber.divide(bNumber);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+            assertEquals("Improper exception message", "Division by zero", e.getMessage());
+        }
+    }
+
+    /**
+     * Divide with ROUND_UNNECESSARY
+     */
+    public void testDivideExceptionRM() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        try {
+            aNumber.divide(bNumber, BigDecimal.ROUND_UNNECESSARY);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+            assertEquals("Improper exception message", "Rounding necessary", e.getMessage());
+        }
+    }
+
+    /**
+     * Divide with invalid rounding mode
+     */
+    public void testDivideExceptionInvalidRM() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        try {
+            aNumber.divide(bNumber, 100);
+            fail("IllegalArgumentException has not been caught");
+        } catch (IllegalArgumentException e) {
+            assertEquals("Improper exception message", "Invalid rounding mode", e.getMessage());
+        }
+    }
+
+    /**
+     * Divide: local variable exponent is less than zero
+     */
+    public void testDivideExpLessZero() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        String c = "1.64770E+10";
+        int resScale = -5;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: local variable exponent is equal to zero
+     */
+    public void testDivideExpEqualsZero() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 10;
+        String c = "1.64769459009933764189139568605273529E+40";
+        int resScale = -5;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: local variable exponent is greater than zero
+     */
+    public void testDivideExpGreaterZero() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -15;
+        String b = "747233429293018787918347987234564568";
+        int bScale = 20;
+        String c = "1.647694590099337641891395686052735285121058381E+50";
+        int resScale = -5;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: remainder is zero
+     */
+    public void testDivideRemainderIsZero() {
+        String a = "8311389578904553209874735431110";
+        int aScale = -15;
+        String b = "237468273682987234567849583746";
+        int bScale = 20;
+        String c = "3.5000000000000000000000000000000E+36";
+        int resScale = -5;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * Divide: rounding mode is ROUND_UP, result is negative
+     */
+    public void testDivideRoundUpNeg() {
+        String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "-1.24390557635720517122423359799284E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_UP);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_UP, result is positive
+     */
+    public void testDivideRoundUpPos() {
+        String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "1.24390557635720517122423359799284E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_UP);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_DOWN, result is negative
+     */
+    public void testDivideRoundDownNeg() {
+        String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "-1.24390557635720517122423359799283E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_DOWN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_DOWN, result is positive
+     */
+    public void testDivideRoundDownPos() {
+        String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "1.24390557635720517122423359799283E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_DOWN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * Divide: rounding mode is ROUND_FLOOR, result is positive
+     */
+    public void testDivideRoundFloorPos() {
+        String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "1.24390557635720517122423359799283E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_FLOOR);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_FLOOR, result is negative
+     */
+    public void testDivideRoundFloorNeg() {
+        String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "-1.24390557635720517122423359799284E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_FLOOR);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * Divide: rounding mode is ROUND_CEILING, result is positive
+     */
+    public void testDivideRoundCeilingPos() {
+        String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "1.24390557635720517122423359799284E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_CEILING, result is negative
+     */
+    public void testDivideRoundCeilingNeg() {
+        String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "-1.24390557635720517122423359799283E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * Divide: rounding mode is ROUND_HALF_UP, result is positive; distance = -1
+     */
+    public void testDivideRoundHalfUpPos() {
+        String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "1.24390557635720517122423359799284E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_UP);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_HALF_UP, result is negative; distance = -1
+     */
+    public void testDivideRoundHalfUpNeg() {
+        String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "-1.24390557635720517122423359799284E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_UP);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * Divide: rounding mode is ROUND_HALF_UP, result is positive; distance = 1
+     */
+    public void testDivideRoundHalfUpPos1() {
+        String a = "92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+        int aScale = -24;
+        String b = "74723342238476237823754692930187879183479";
+        int bScale = 13;
+        String c = "1.2439055763572051712242335979928354832010167729111113605E+76";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_UP);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_HALF_UP, result is negative; distance = 1
+     */
+    public void testDivideRoundHalfUpNeg1() {
+        String a = "-92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+        int aScale = -24;
+        String b = "74723342238476237823754692930187879183479";
+        int bScale = 13;
+        String c = "-1.2439055763572051712242335979928354832010167729111113605E+76";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_UP);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * Divide: rounding mode is ROUND_HALF_UP, result is negative; equidistant
+     */
+    public void testDivideRoundHalfUpNeg2() {
+        String a = "-37361671119238118911893939591735";
+        int aScale = 10;
+        String b = "74723342238476237823787879183470";
+        int bScale = 15;
+        String c = "-1E+5";
+        int resScale = -5;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_UP);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * Divide: rounding mode is ROUND_HALF_DOWN, result is positive; distance = -1
+     */
+    public void testDivideRoundHalfDownPos() {
+        String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "1.24390557635720517122423359799284E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_DOWN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_HALF_DOWN, result is negative; distance = -1
+     */
+    public void testDivideRoundHalfDownNeg() {
+        String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "-1.24390557635720517122423359799284E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_DOWN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * Divide: rounding mode is ROUND_HALF_DOWN, result is positive; distance = 1
+     */
+    public void testDivideRoundHalfDownPos1() {
+        String a = "92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+        int aScale = -24;
+        String b = "74723342238476237823754692930187879183479";
+        int bScale = 13;
+        String c = "1.2439055763572051712242335979928354832010167729111113605E+76";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_DOWN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_HALF_DOWN, result is negative; distance = 1
+     */
+    public void testDivideRoundHalfDownNeg1() {
+        String a = "-92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+        int aScale = -24;
+        String b = "74723342238476237823754692930187879183479";
+        int bScale = 13;
+        String c = "-1.2439055763572051712242335979928354832010167729111113605E+76";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_DOWN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_HALF_UP, result is negative; equidistant
+     */
+    public void testDivideRoundHalfDownNeg2() {
+        String a = "-37361671119238118911893939591735";
+        int aScale = 10;
+        String b = "74723342238476237823787879183470";
+        int bScale = 15;
+        String c = "0E+5";
+        int resScale = -5;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_DOWN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_HALF_EVEN, result is positive; distance = -1
+     */
+    public void testDivideRoundHalfEvenPos() {
+        String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "1.24390557635720517122423359799284E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_EVEN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_HALF_EVEN, result is negative; distance = -1
+     */
+    public void testDivideRoundHalfEvenNeg() {
+        String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+        int aScale = -24;
+        String b = "7472334223847623782375469293018787918347987234564568";
+        int bScale = 13;
+        String c = "-1.24390557635720517122423359799284E+53";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_EVEN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * Divide: rounding mode is ROUND_HALF_EVEN, result is positive; distance = 1
+     */
+    public void testDivideRoundHalfEvenPos1() {
+        String a = "92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+        int aScale = -24;
+        String b = "74723342238476237823754692930187879183479";
+        int bScale = 13;
+        String c = "1.2439055763572051712242335979928354832010167729111113605E+76";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_EVEN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_HALF_EVEN, result is negative; distance = 1
+     */
+    public void testDivideRoundHalfEvenNeg1() {
+        String a = "-92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+        int aScale = -24;
+        String b = "74723342238476237823754692930187879183479";
+        int bScale = 13;
+        String c = "-1.2439055763572051712242335979928354832010167729111113605E+76";
+        int resScale = -21;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_EVEN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide: rounding mode is ROUND_HALF_EVEN, result is negative; equidistant
+     */
+    public void testDivideRoundHalfEvenNeg2() {
+        String a = "-37361671119238118911893939591735";
+        int aScale = 10;
+        String b = "74723342238476237823787879183470";
+        int bScale = 15;
+        String c = "0E+5";
+        int resScale = -5;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_EVEN);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide to BigDecimal
+     */
+    public void testDivideBigDecimal1() {
+        String a = "-37361671119238118911893939591735";
+        int aScale = 10;
+        String b = "74723342238476237823787879183470";
+        int bScale = 15;
+        String c = "-5E+4";
+        int resScale = -4;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Divide to BigDecimal
+     */
+    public void testDivideBigDecimal2() {
+        String a = "-37361671119238118911893939591735";
+        int aScale = 10;
+        String b = "74723342238476237823787879183470";
+        int bScale = -15;
+        String c = "-5E-26";
+        int resScale = 26;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, scale, RoundingMode)
+     */
+    public void testDivideBigDecimalScaleRoundingModeUP() {
+        String a = "-37361671119238118911893939591735";
+        int aScale = 10;
+        String b = "74723342238476237823787879183470";
+        int bScale = -15;
+        int newScale = 31;
+        RoundingMode rm = RoundingMode.UP;
+        String c = "-5.00000E-26";
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", newScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, scale, RoundingMode)
+     */
+    public void testDivideBigDecimalScaleRoundingModeDOWN() {
+        String a = "-37361671119238118911893939591735";
+        int aScale = 10;
+        String b = "74723342238476237823787879183470";
+        int bScale = 15;
+        int newScale = 31;
+        RoundingMode rm = RoundingMode.DOWN;
+        String c = "-50000.0000000000000000000000000000000";
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", newScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, scale, RoundingMode)
+     */
+    public void testDivideBigDecimalScaleRoundingModeCEILING() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 100;
+        String b = "74723342238476237823787879183470";
+        int bScale = 15;
+        int newScale = 45;
+        RoundingMode rm = RoundingMode.CEILING;
+        String c = "1E-45";
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", newScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, scale, RoundingMode)
+     */
+    public void testDivideBigDecimalScaleRoundingModeFLOOR() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 100;
+        String b = "74723342238476237823787879183470";
+        int bScale = 15;
+        int newScale = 45;
+        RoundingMode rm = RoundingMode.FLOOR;
+        String c = "0E-45";
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", newScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, scale, RoundingMode)
+     */
+    public void testDivideBigDecimalScaleRoundingModeHALF_UP() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = -51;
+        String b = "74723342238476237823787879183470";
+        int bScale = 45;
+        int newScale = 3;
+        RoundingMode rm = RoundingMode.HALF_UP;
+        String c = "50000260373164286401361913262100972218038099522752460421" +
+                   "05959924024355721031761947728703598332749334086415670525" +
+                   "3761096961.670";
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", newScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, scale, RoundingMode)
+     */
+    public void testDivideBigDecimalScaleRoundingModeHALF_DOWN() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 5;
+        String b = "74723342238476237823787879183470";
+        int bScale = 15;
+        int newScale = 7;
+        RoundingMode rm = RoundingMode.HALF_DOWN;
+        String c = "500002603731642864013619132621009722.1803810";
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", newScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, scale, RoundingMode)
+     */
+    public void testDivideBigDecimalScaleRoundingModeHALF_EVEN() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 5;
+        String b = "74723342238476237823787879183470";
+        int bScale = 15;
+        int newScale = 7;
+        RoundingMode rm = RoundingMode.HALF_EVEN;
+        String c = "500002603731642864013619132621009722.1803810";
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", newScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, MathContext)
+     */
+    public void testDivideBigDecimalScaleMathContextUP() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 15;
+        String b = "748766876876723342238476237823787879183470";
+        int bScale = 10;
+        int precision = 21;
+        RoundingMode rm = RoundingMode.UP;
+        MathContext mc = new MathContext(precision, rm);
+        String c = "49897861180.2562512996";
+        int resScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, MathContext)
+     */
+    public void testDivideBigDecimalScaleMathContextDOWN() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 15;
+        String b = "748766876876723342238476237823787879183470";
+        int bScale = 70;
+        int precision = 21;
+        RoundingMode rm = RoundingMode.DOWN;
+        MathContext mc = new MathContext(precision, rm);
+        String c = "4.98978611802562512995E+70";
+        int resScale = -50;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, MathContext)
+     */
+    public void testDivideBigDecimalScaleMathContextCEILING() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 15;
+        String b = "748766876876723342238476237823787879183470";
+        int bScale = 70;
+        int precision = 21;
+        RoundingMode rm = RoundingMode.CEILING;
+        MathContext mc = new MathContext(precision, rm);
+        String c = "4.98978611802562512996E+70";
+        int resScale = -50;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, MathContext)
+     */
+    public void testDivideBigDecimalScaleMathContextFLOOR() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 15;
+        String b = "748766876876723342238476237823787879183470";
+        int bScale = 70;
+        int precision = 21;
+        RoundingMode rm = RoundingMode.FLOOR;
+        MathContext mc = new MathContext(precision, rm);
+        String c = "4.98978611802562512995E+70";
+        int resScale = -50;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, MathContext)
+     */
+    public void testDivideBigDecimalScaleMathContextHALF_UP() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 70;
+        int precision = 21;
+        RoundingMode rm = RoundingMode.HALF_UP;
+        MathContext mc = new MathContext(precision, rm);
+        String c = "2.77923185514690367475E+26";
+        int resScale = -6;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, MathContext)
+     */
+    public void testDivideBigDecimalScaleMathContextHALF_DOWN() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 70;
+        int precision = 21;
+        RoundingMode rm = RoundingMode.HALF_DOWN;
+        MathContext mc = new MathContext(precision, rm);
+        String c = "2.77923185514690367475E+26";
+        int resScale = -6;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * divide(BigDecimal, MathContext)
+     */
+    public void testDivideBigDecimalScaleMathContextHALF_EVEN() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 70;
+        int precision = 21;
+        RoundingMode rm = RoundingMode.HALF_EVEN;
+        MathContext mc = new MathContext(precision, rm);
+        String c = "2.77923185514690367475E+26";
+        int resScale = -6;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divide(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+
+    /**
+     * BigDecimal.divide with a scale that's too large
+     * 
+     * Regression test for HARMONY-6271
+     */
+    public void testDivideLargeScale() {
+    	BigDecimal arg1 = new BigDecimal("320.0E+2147483647");
+		BigDecimal arg2 = new BigDecimal("6E-2147483647");
+    	try {
+    		BigDecimal result = arg1.divide(arg2, Integer.MAX_VALUE, 
+    				java.math.RoundingMode.CEILING);
+    		fail("Expected ArithmeticException when dividing with a scale that's too large");
+    	} catch (ArithmeticException e) {
+    		// expected behaviour
+    	}
+    }
+
+    /**
+     * divideToIntegralValue(BigDecimal)
+     */
+    public void testDivideToIntegralValue() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 70;
+        String c = "277923185514690367474770683";
+        int resScale = 0;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divideToIntegralValue(bNumber);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * divideToIntegralValue(BigDecimal, MathContext)
+     */
+    public void testDivideToIntegralValueMathContextUP() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 70;
+        int precision = 32;
+        RoundingMode rm = RoundingMode.UP;
+        MathContext mc = new MathContext(precision, rm);
+        String c = "277923185514690367474770683";
+        int resScale = 0;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divideToIntegralValue(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * divideToIntegralValue(BigDecimal, MathContext)
+     */
+    public void testDivideToIntegralValueMathContextDOWN() {
+        String a = "3736186567876876578956958769675785435673453453653543654354365435675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 70;
+        int precision = 75;
+        RoundingMode rm = RoundingMode.DOWN;
+        MathContext mc = new MathContext(precision, rm);
+        String c = "2.7792318551469036747477068339450205874992634417590178670822889E+62";
+        int resScale = -1;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.divideToIntegralValue(bNumber, mc);
+        assertEquals("incorrect value", c, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * divideAndRemainder(BigDecimal)
+     */
+    public void testDivideAndRemainder1() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 70;
+        String res = "277923185514690367474770683";
+        int resScale = 0;
+        String rem = "1.3032693871288309587558885943391070087960319452465789990E-15";
+        int remScale = 70;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result[] = aNumber.divideAndRemainder(bNumber);
+        assertEquals("incorrect quotient value", res, result[0].toString());
+        assertEquals("incorrect quotient scale", resScale, result[0].scale());
+        assertEquals("incorrect remainder value", rem, result[1].toString());
+        assertEquals("incorrect remainder scale", remScale, result[1].scale());
+    }
+
+    /**
+     * divideAndRemainder(BigDecimal)
+     */
+    public void testDivideAndRemainder2() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = -45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 70;
+        String res = "2779231855146903674747706830969461168692256919247547952" +
+                     "2608549363170374005512836303475980101168105698072946555" +
+                     "6862849";
+        int resScale = 0;
+        String rem = "3.4935796954060524114470681810486417234751682675102093970E-15";
+        int remScale = 70;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result[] = aNumber.divideAndRemainder(bNumber);
+        assertEquals("incorrect quotient value", res, result[0].toString());
+        assertEquals("incorrect quotient scale", resScale, result[0].scale());
+        assertEquals("incorrect remainder value", rem, result[1].toString());
+        assertEquals("incorrect remainder scale", remScale, result[1].scale());
+    }
+    
+    /**
+     * divideAndRemainder(BigDecimal, MathContext)
+     */
+    public void testDivideAndRemainderMathContextUP() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 70;
+        int precision = 75;
+        RoundingMode rm = RoundingMode.UP;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "277923185514690367474770683";
+        int resScale = 0;
+        String rem = "1.3032693871288309587558885943391070087960319452465789990E-15";
+        int remScale = 70;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result[] = aNumber.divideAndRemainder(bNumber, mc);
+        assertEquals("incorrect quotient value", res, result[0].toString());
+        assertEquals("incorrect quotient scale", resScale, result[0].scale());
+        assertEquals("incorrect remainder value", rem, result[1].toString());
+        assertEquals("incorrect remainder scale", remScale, result[1].scale());
+    }
+
+    /**
+     * divideAndRemainder(BigDecimal, MathContext)
+     */
+    public void testDivideAndRemainderMathContextDOWN() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 20;
+        int precision = 15;
+        RoundingMode rm = RoundingMode.DOWN;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "0E-25";
+        int resScale = 25;
+        String rem = "3736186567876.876578956958765675671119238118911893939591735";
+        int remScale = 45;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result[] = aNumber.divideAndRemainder(bNumber, mc);
+        assertEquals("incorrect quotient value", res, result[0].toString());
+        assertEquals("incorrect quotient scale", resScale, result[0].scale());
+        assertEquals("incorrect remainder value", rem, result[1].toString());
+        assertEquals("incorrect remainder scale", remScale, result[1].scale());
+    }
+    
+    /**
+     * remainder(BigDecimal)
+     */
+    public void testRemainder1() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 10;
+        String res = "3736186567876.876578956958765675671119238118911893939591735";
+        int resScale = 45;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.remainder(bNumber);
+        assertEquals("incorrect quotient value", res, result.toString());
+        assertEquals("incorrect quotient scale", resScale, result.scale());
+    }
+
+    /**
+     * remainder(BigDecimal)
+     */
+    public void testRemainder2() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = -45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 10;
+        String res = "1149310942946292909508821656680979993738625937.2065885780";
+        int resScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.remainder(bNumber);
+        assertEquals("incorrect quotient value", res, result.toString());
+        assertEquals("incorrect quotient scale", resScale, result.scale());
+    }
+
+    /**
+     * remainder(BigDecimal, MathContext)
+     */
+    public void testRemainderMathContextHALF_UP() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 10;
+        int precision = 15;
+        RoundingMode rm = RoundingMode.HALF_UP;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "3736186567876.876578956958765675671119238118911893939591735";
+        int resScale = 45;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.remainder(bNumber, mc);
+        assertEquals("incorrect quotient value", res, result.toString());
+        assertEquals("incorrect quotient scale", resScale, result.scale());
+    }
+
+    /**
+     * remainder(BigDecimal, MathContext)
+     */
+    public void testRemainderMathContextHALF_DOWN() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = -45;
+        String b = "134432345432345748766876876723342238476237823787879183470";
+        int bScale = 10;
+        int precision = 75;
+        RoundingMode rm = RoundingMode.HALF_DOWN;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "1149310942946292909508821656680979993738625937.2065885780";
+        int resScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        BigDecimal result = aNumber.remainder(bNumber, mc);
+        assertEquals("incorrect quotient value", res, result.toString());
+        assertEquals("incorrect quotient scale", resScale, result.scale());
+    }
+
+    /**
+     * round(BigDecimal, MathContext)
+     */
+    public void testRoundMathContextHALF_DOWN() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = -45;
+        int precision = 75;
+        RoundingMode rm = RoundingMode.HALF_DOWN;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "3.736186567876876578956958765675671119238118911893939591735E+102";
+        int resScale = -45;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.round(mc);
+        assertEquals("incorrect quotient value", res, result.toString());
+        assertEquals("incorrect quotient scale", resScale, result.scale());
+    }
+
+    /**
+     * round(BigDecimal, MathContext)
+     */
+    public void testRoundMathContextHALF_UP() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        int precision = 15;
+        RoundingMode rm = RoundingMode.HALF_UP;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "3736186567876.88";
+        int resScale = 2;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.round(mc);
+        assertEquals("incorrect quotient value", res, result.toString());
+        assertEquals("incorrect quotient scale", resScale, result.scale());
+    }
+
+    /**
+     * round(BigDecimal, MathContext) when precision = 0
+     */
+    public void testRoundMathContextPrecision0() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        int precision = 0;
+        RoundingMode rm = RoundingMode.HALF_UP;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "3736186567876.876578956958765675671119238118911893939591735";
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.round(mc);
+        assertEquals("incorrect quotient value", res, result.toString());
+        assertEquals("incorrect quotient scale", aScale, result.scale());
+    }
+
+
+    /**
+     * ulp() of a positive BigDecimal
+     */
+    public void testUlpPos() {
+        String a = "3736186567876876578956958765675671119238118911893939591735";
+        int aScale = -45;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.ulp();
+        String res = "1E+45";
+        int resScale = -45;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * ulp() of a negative BigDecimal
+     */
+    public void testUlpNeg() {
+        String a = "-3736186567876876578956958765675671119238118911893939591735";
+        int aScale = 45;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.ulp();
+        String res = "1E-45";
+        int resScale = 45;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * ulp() of a negative BigDecimal
+     */
+    public void testUlpZero() {
+        String a = "0";
+        int aScale = 2;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.ulp();
+        String res = "0.01";
+        int resScale = 2;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalCompareTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalCompareTest.java
new file mode 100644
index 0000000..df756a1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalCompareTest.java
@@ -0,0 +1,512 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+import junit.framework.TestCase;
+
+/**
+ * Class:  java.math.BigDecimal
+ * Methods: abs, compareTo, equals, hashCode, 
+ * max, min, negate, signum
+ */
+public class BigDecimalCompareTest extends TestCase {
+    /**
+     * Abs() of a negative BigDecimal
+     */
+    public void testAbsNeg() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "123809648392384754573567356745735635678902957849027687.87678287";
+        assertEquals("incorrect value", result, aNumber.abs().toString());
+    }
+
+    /**
+     * Abs() of a positive BigDecimal
+     */
+    public void testAbsPos() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "123809648392384754573567356745735635678902957849027687.87678287";
+        assertEquals("incorrect value", result, aNumber.abs().toString());
+    }
+
+    /**
+     * Abs(MathContext) of a negative BigDecimal
+     */
+    public void testAbsMathContextNeg() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        int precision = 15;
+        RoundingMode rm = RoundingMode.HALF_DOWN;
+        MathContext mc = new MathContext(precision, rm);
+        String result = "1.23809648392385E+53";
+        int resScale = -39;
+        BigDecimal res = aNumber.abs(mc);
+        assertEquals("incorrect value", result, res.toString());
+        assertEquals("incorrect scale", resScale, res.scale());
+    }
+
+    /**
+     * Abs(MathContext) of a positive BigDecimal
+     */
+    public void testAbsMathContextPos() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        int precision = 41;
+        RoundingMode rm = RoundingMode.HALF_EVEN;
+        MathContext mc = new MathContext(precision, rm);
+        String result = "1.2380964839238475457356735674573563567890E+53";
+        int resScale = -13;
+        BigDecimal res = aNumber.abs(mc);
+        assertEquals("incorrect value", result, res.toString());
+        assertEquals("incorrect scale", resScale, res.scale());
+    }
+
+    /**
+     * Compare to a number of an equal scale
+     */
+    public void testCompareEqualScale1() {
+        String a = "12380964839238475457356735674573563567890295784902768787678287";
+        int aScale = 18;
+        String b = "4573563567890295784902768787678287";
+        int bScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        int result = 1;
+        assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * Compare to a number of an equal scale
+     */
+    public void testCompareEqualScale2() {
+        String a = "12380964839238475457356735674573563567890295784902768787678287";
+        int aScale = 18;
+        String b = "4573563923487289357829759278282992758247567890295784902768787678287";
+        int bScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        int result = -1;
+        assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * Compare to a number of an greater scale
+     */
+    public void testCompareGreaterScale1() {
+        String a = "12380964839238475457356735674573563567890295784902768787678287";
+        int aScale = 28;
+        String b = "4573563567890295784902768787678287";
+        int bScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        int result = 1;
+        assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * Compare to a number of an greater scale
+     */
+    public void testCompareGreaterScale2() {
+        String a = "12380964839238475457356735674573563567890295784902768787678287";
+        int aScale = 48;
+        String b = "4573563567890295784902768787678287";
+        int bScale = 2;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        int result = -1;
+        assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * Compare to a number of an less scale
+     */
+    public void testCompareLessScale1() {
+        String a = "12380964839238475457356735674573563567890295784902768787678287";
+        int aScale = 18;
+        String b = "4573563567890295784902768787678287";
+        int bScale = 28;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        int result = 1;
+        assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * Compare to a number of an less scale
+     */
+    public void testCompareLessScale2() {
+        String a = "12380964839238475457356735674573";
+        int aScale = 36;
+        String b = "45735635948573894578349572001798379183767890295784902768787678287";
+        int bScale = 48;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+        int result = -1;
+        assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * Equals() for unequal BigDecimals
+     */
+    public void testEqualsUnequal1() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = -24;
+       String b = "7472334223847623782375469293018787918347987234564568";
+       int bScale = 13;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       assertFalse(aNumber.equals(bNumber));
+    }
+
+    /**
+     * Equals() for unequal BigDecimals
+     */
+    public void testEqualsUnequal2() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = -24;
+       String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int bScale = 13;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       assertFalse(aNumber.equals(bNumber));
+    }
+
+    /**
+     * Equals() for unequal BigDecimals
+     */
+    public void testEqualsUnequal3() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = -24;
+       String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       assertFalse(aNumber.equals(b));
+    }
+
+    /**
+     * equals() for equal BigDecimals
+     */
+    public void testEqualsEqual() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = -24;
+       String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int bScale = -24;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       assertEquals(aNumber, bNumber);
+    }
+
+    /**
+     * equals() for equal BigDecimals
+     */
+    public void testEqualsNull() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = -24;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       assertFalse(aNumber.equals(null));
+    }
+
+    /**
+     * hashCode() for equal BigDecimals
+     */
+    public void testHashCodeEqual() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = -24;
+       String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int bScale = -24;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       assertEquals("incorrect value", aNumber.hashCode(), bNumber.hashCode());
+    }
+
+    /**
+     * hashCode() for unequal BigDecimals
+     */
+    public void testHashCodeUnequal() {
+       String a = "8478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int bScale = -24;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       assertTrue("incorrect value", aNumber.hashCode() != bNumber.hashCode());
+    }
+
+    /**
+     * max() for equal BigDecimals
+     */
+    public void testMaxEqual() {
+       String a = "8478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       String b = "8478231212478987482988429808779810457634781384756794987";
+       int bScale = 41;
+       String c = "8478231212478987482988429808779810457634781384756794987";
+       int cScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+       assertEquals("incorrect value", cNumber, aNumber.max(bNumber));
+    }
+
+    /**
+     * max() for unequal BigDecimals
+     */
+    public void testMaxUnequal1() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 24;
+       String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int bScale = 41;
+       String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int cScale = 24;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+       assertEquals("incorrect value", cNumber, aNumber.max(bNumber));
+    }
+
+    /**
+     * max() for unequal BigDecimals
+     */
+    public void testMaxUnequal2() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       String b = "94488478231212478987482988429808779810457634781384756794987";
+       int bScale = 41;
+       String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int cScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+       assertEquals("incorrect value", cNumber, aNumber.max(bNumber));
+    }
+
+    /**
+     * min() for equal BigDecimals
+     */
+    public void testMinEqual() {
+       String a = "8478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       String b = "8478231212478987482988429808779810457634781384756794987";
+       int bScale = 41;
+       String c = "8478231212478987482988429808779810457634781384756794987";
+       int cScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+       assertEquals("incorrect value", cNumber, aNumber.min(bNumber));
+    }
+
+    /**
+     * min() for unequal BigDecimals
+     */
+    public void testMinUnequal1() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 24;
+       String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int bScale = 41;
+       String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int cScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+       assertEquals("incorrect value", cNumber, aNumber.min(bNumber));
+    }
+
+    /**
+     * min() for unequal BigDecimals
+     */
+    public void testMinUnequal2() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       String b = "94488478231212478987482988429808779810457634781384756794987";
+       int bScale = 41;
+       String c = "94488478231212478987482988429808779810457634781384756794987";
+       int cScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+       BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+       assertEquals("incorrect value", cNumber, aNumber.min(bNumber));
+    }
+
+    /**
+     * plus() for a positive BigDecimal
+     */
+    public void testPlusPositive() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int cScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+       assertEquals("incorrect value", cNumber, aNumber.plus());
+    }
+
+    /**
+     * plus(MathContext) for a positive BigDecimal
+     */
+    public void testPlusMathContextPositive() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       int precision = 37;
+       RoundingMode rm = RoundingMode.FLOOR;
+       MathContext mc = new MathContext(precision, rm);
+       String c = "929487820944884782312124789.8748298842";
+       int cScale = 10;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal res = aNumber.plus(mc);
+       assertEquals("incorrect value", c, res.toString());
+       assertEquals("incorrect scale", cScale, res.scale());
+    }
+
+    /**
+     * plus() for a negative BigDecimal
+     */
+    public void testPlusNegative() {
+       String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       String c = "-92948782094488478231212478987482988429808779810457634781384756794987";
+       int cScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+       assertEquals("incorrect value", cNumber, aNumber.plus());
+    }
+
+    /**
+     * plus(MathContext) for a negative BigDecimal
+     */
+    public void testPlusMathContextNegative() {
+       String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 49;
+       int precision = 46;
+       RoundingMode rm = RoundingMode.CEILING;
+       MathContext mc = new MathContext(precision, rm);
+       String c = "-9294878209448847823.121247898748298842980877981";
+       int cScale = 27;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal res = aNumber.plus(mc);
+       assertEquals("incorrect value", c, res.toString());
+       assertEquals("incorrect scale", cScale, res.scale());
+    }
+
+    /**
+     * negate() for a positive BigDecimal
+     */
+    public void testNegatePositive() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       String c = "-92948782094488478231212478987482988429808779810457634781384756794987";
+       int cScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+       assertEquals("incorrect value", cNumber, aNumber.negate());
+    }
+
+    /**
+     * negate(MathContext) for a positive BigDecimal
+     */
+    public void testNegateMathContextPositive() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       int precision = 37;
+       RoundingMode rm = RoundingMode.FLOOR;
+       MathContext mc = new MathContext(precision, rm);
+       String c = "-929487820944884782312124789.8748298843";
+       int cScale = 10;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal res = aNumber.negate(mc);
+       assertEquals("incorrect value", c, res.toString());
+       assertEquals("incorrect scale", cScale, res.scale());
+    }
+
+    /**
+     * negate() for a negative BigDecimal
+     */
+    public void testNegateNegative() {
+       String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int cScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+       assertEquals("incorrect value", cNumber, aNumber.negate());
+    }
+
+    /**
+     * negate(MathContext) for a negative BigDecimal
+     */
+    public void testNegateMathContextNegative() {
+       String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 49;
+       int precision = 46;
+       RoundingMode rm = RoundingMode.CEILING;
+       MathContext mc = new MathContext(precision, rm);
+       String c = "9294878209448847823.121247898748298842980877982";
+       int cScale = 27;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       BigDecimal res = aNumber.negate(mc);
+       assertEquals("incorrect value", c, res.toString());
+       assertEquals("incorrect scale", cScale, res.scale());
+    }
+
+    /**
+     * signum() for a positive BigDecimal
+     */
+    public void testSignumPositive() {
+       String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       assertEquals("incorrect value", 1, aNumber.signum());
+    }
+
+    /**
+     * signum() for a negative BigDecimal
+     */
+    public void testSignumNegative() {
+       String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+       int aScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       assertEquals("incorrect value", -1, aNumber.signum());
+    }
+
+    /**
+     * signum() for zero
+     */
+    public void testSignumZero() {
+       String a = "0";
+       int aScale = 41;
+       BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+       assertEquals("incorrect value", 0, aNumber.signum());
+    }
+    
+    /*
+     * Regression test for HARMONY-6406
+     */
+    public void testApproxPrecision() {
+        BigDecimal testInstance = BigDecimal.TEN.multiply(new BigDecimal("0.1"));
+        int result = testInstance.compareTo(new BigDecimal("1.00"));
+        assertEquals(0, result);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConstructorsTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConstructorsTest.java
new file mode 100644
index 0000000..3838991
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConstructorsTest.java
@@ -0,0 +1,684 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+import junit.framework.TestCase;
+
+/**
+ * Class:  java.math.BigDecimal
+ * Methods: constructors and fields
+ */
+public class BigDecimalConstructorsTest extends TestCase {
+    /**
+     * check ONE
+     */
+    public void testFieldONE() {
+        String oneS = "1";
+        double oneD = 1.0;
+        assertEquals("incorrect string value", oneS, BigDecimal.ONE.toString());
+        assertEquals("incorrect double value", oneD, BigDecimal.ONE.doubleValue(), 0);
+    }
+
+    /**
+     * check TEN
+     */
+    public void testFieldTEN() {
+        String oneS = "10";
+        double oneD = 10.0;
+        assertEquals("incorrect string value", oneS, BigDecimal.TEN.toString());
+        assertEquals("incorrect double value", oneD, BigDecimal.TEN.doubleValue(), 0);
+    }
+
+    /**
+     * check ZERO
+     */
+    public void testFieldZERO() {
+        String oneS = "0";
+        double oneD = 0.0;
+        assertEquals("incorrect string value", oneS, BigDecimal.ZERO.toString());
+        assertEquals("incorrect double value", oneD, BigDecimal.ZERO.doubleValue(), 0);
+    }
+
+    /**
+     * new BigDecimal(BigInteger value)
+     */
+    public void testConstrBI() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        BigInteger bA = new BigInteger(a);
+        BigDecimal aNumber = new BigDecimal(bA);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", 0, aNumber.scale());
+
+        try {
+            new BigDecimal((BigInteger) null);
+        	fail("No NullPointerException");
+        } catch (NullPointerException e) {
+        	//expected
+        }
+    }
+     
+    /**
+     * new BigDecimal(BigInteger value, int scale)
+     */
+    public void testConstrBIScale() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        BigInteger bA = new BigInteger(a);
+        int aScale = 10;
+        BigDecimal aNumber = new BigDecimal(bA, aScale);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(BigInteger value, MathContext)
+     */
+    public void testConstrBigIntegerMathContext() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        BigInteger bA = new BigInteger(a);
+        int precision = 46;
+        RoundingMode rm = RoundingMode.CEILING;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "1231212478987482988429808779810457634781384757";
+        int resScale = -6;
+        BigDecimal result = new BigDecimal(bA, mc);
+        assertEquals("incorrect value", res, result.unscaledValue().toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * new BigDecimal(BigInteger value, int scale, MathContext)
+     */
+    public void testConstrBigIntegerScaleMathContext() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        BigInteger bA = new BigInteger(a);
+        int aScale = 10;
+        int precision = 46;
+        RoundingMode rm = RoundingMode.CEILING;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "1231212478987482988429808779810457634781384757";
+        int resScale = 4;
+        BigDecimal result = new BigDecimal(bA, aScale, mc);
+        assertEquals("incorrect value", res, result.unscaledValue().toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * new BigDecimal(char[] value); 
+     */
+    public void testConstrChar() {
+        char value[] = {'-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4', '2', '3'};
+        BigDecimal result = new BigDecimal(value);
+        String res = "-1.23804738E-419";
+        int resScale = 427;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+        
+        try {
+            // Regression for HARMONY-783
+            new BigDecimal(new char[] {});
+            fail("NumberFormatException has not been thrown");
+        } catch (NumberFormatException e) {
+        }
+     }
+    
+    /**
+     * new BigDecimal(char[] value, int offset, int len); 
+     */
+    public void testConstrCharIntInt() {
+        char value[] = {'-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4', '2', '3'};
+        int offset = 3;
+        int len = 12;
+        BigDecimal result = new BigDecimal(value, offset, len);
+        String res = "3.804738E-40";
+        int resScale = 46;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+        
+        try {
+            // Regression for HARMONY-783
+            new BigDecimal(new char[] {}, 0, 0);
+            fail("NumberFormatException has not been thrown");
+        } catch (NumberFormatException e) {
+        }
+     }
+    
+    /**
+     * new BigDecimal(char[] value, int offset, int len, MathContext mc); 
+     */
+    public void testConstrCharIntIntMathContext() {
+        char value[] = {'-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4', '2', '3'};
+        int offset = 3;
+        int len = 12;
+        int precision = 4;
+        RoundingMode rm = RoundingMode.CEILING;
+        MathContext mc = new MathContext(precision, rm);
+        BigDecimal result = new BigDecimal(value, offset, len, mc);
+        String res = "3.805E-40";
+        int resScale = 43;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+        
+        try {
+            // Regression for HARMONY-783
+            new BigDecimal(new char[] {}, 0, 0, MathContext.DECIMAL32);
+            fail("NumberFormatException has not been thrown");
+        } catch (NumberFormatException e) {
+        }
+     }
+    
+    /**
+     * new BigDecimal(char[] value, int offset, int len, MathContext mc); 
+     */
+    public void testConstrCharIntIntMathContextException1() {
+        char value[] = {'-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4', '2', '3'};
+        int offset = 3;
+        int len = 120;
+        int precision = 4;
+        RoundingMode rm = RoundingMode.CEILING;
+        MathContext mc = new MathContext(precision, rm);
+        try {
+            new BigDecimal(value, offset, len, mc);
+            fail("NumberFormatException has not been thrown");
+        } catch (NumberFormatException e) {
+        }
+     }
+    
+    /**
+     * new BigDecimal(char[] value, int offset, int len, MathContext mc); 
+     */
+    public void testConstrCharIntIntMathContextException2() {
+        char value[] = {'-', '1', '2', '3', '8', '0', ',', '4', '7', '3', '8', 'E', '-', '4', '2', '3'};
+        int offset = 3;
+        int len = 120;
+        int precision = 4;
+        RoundingMode rm = RoundingMode.CEILING;
+        MathContext mc = new MathContext(precision, rm);
+        try {
+            new BigDecimal(value, offset, len, mc);
+            fail("NumberFormatException has not been thrown");
+        } catch (NumberFormatException e) {
+        }
+     }
+
+    /**
+     * new BigDecimal(char[] value, MathContext mc);
+     */
+    public void testConstrCharMathContext() {
+        try {
+            // Regression for HARMONY-783
+            new BigDecimal(new char[] {}, MathContext.DECIMAL32);
+            fail("NumberFormatException has not been thrown");
+        } catch (NumberFormatException e) {
+        }
+    }
+    
+    /**
+     * new BigDecimal(double value) when value is NaN
+     */
+    public void testConstrDoubleNaN() {
+        double a = Double.NaN;
+        try {
+            new BigDecimal(a);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+
+    /**
+     * new BigDecimal(double value) when value is positive infinity
+     */
+    public void testConstrDoublePosInfinity() {
+        double a = Double.POSITIVE_INFINITY;
+        try {
+            new BigDecimal(a);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+
+    /**
+     * new BigDecimal(double value) when value is positive infinity
+     */
+    public void testConstrDoubleNegInfinity() {
+        double a = Double.NEGATIVE_INFINITY;
+        try {
+            new BigDecimal(a);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+
+    /**
+     * new BigDecimal(double value)
+     */
+    public void testConstrDouble() {
+        double a = 732546982374982347892379283571094797.287346782359284756;
+        int aScale = 0;
+        BigInteger bA = new BigInteger("732546982374982285073458350476230656");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(double, MathContext)
+     */
+    public void testConstrDoubleMathContext() {
+        double a = 732546982374982347892379283571094797.287346782359284756;
+        int precision = 21;
+        RoundingMode rm = RoundingMode.CEILING;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "732546982374982285074";
+        int resScale = -15;
+        BigDecimal result = new BigDecimal(a, mc);
+        assertEquals("incorrect value", res, result.unscaledValue().toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * new BigDecimal(0.1)
+     */
+    public void testConstrDouble01() {
+        double a = 1.E-1;
+        int aScale = 55;
+        BigInteger bA = new BigInteger("1000000000000000055511151231257827021181583404541015625");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(0.555)
+     */
+    public void testConstrDouble02() {
+        double a = 0.555;
+        int aScale = 53;
+        BigInteger bA = new BigInteger("55500000000000004884981308350688777863979339599609375");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(-0.1)
+     */
+    public void testConstrDoubleMinus01() {
+        double a = -1.E-1;
+        int aScale = 55;
+        BigInteger bA = new BigInteger("-1000000000000000055511151231257827021181583404541015625");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(int value)
+     */
+    public void testConstrInt() {
+        int a = 732546982;
+        String res = "732546982";
+        int resScale = 0;
+        BigDecimal result = new BigDecimal(a);
+        assertEquals("incorrect value", res, result.unscaledValue().toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * new BigDecimal(int, MathContext)
+     */
+    public void testConstrIntMathContext() {
+        int a = 732546982;
+        int precision = 21;
+        RoundingMode rm = RoundingMode.CEILING;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "732546982";
+        int resScale = 0;
+        BigDecimal result = new BigDecimal(a, mc);
+        assertEquals("incorrect value", res, result.unscaledValue().toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * new BigDecimal(long value)
+     */
+    public void testConstrLong() {
+        long a = 4576578677732546982L;
+        String res = "4576578677732546982";
+        int resScale = 0;
+        BigDecimal result = new BigDecimal(a);
+        assertEquals("incorrect value", res, result.unscaledValue().toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * new BigDecimal(long, MathContext)
+     */
+    public void testConstrLongMathContext() {
+        long a = 4576578677732546982L;
+        int precision = 5;
+        RoundingMode rm = RoundingMode.CEILING;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "45766";
+        int resScale = -14;
+        BigDecimal result = new BigDecimal(a, mc);
+        assertEquals("incorrect value", res, result.unscaledValue().toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * new BigDecimal(double value) when value is denormalized
+     */
+    public void testConstrDoubleDenormalized() {
+        double a = 2.274341322658976E-309;
+        int aScale = 1073;
+        BigInteger bA = new BigInteger("227434132265897633950269241702666687639731047124115603942986140264569528085692462493371029187342478828091760934014851133733918639492582043963243759464684978401240614084312038547315281016804838374623558434472007664427140169018817050565150914041833284370702366055678057809362286455237716100382057360123091641959140448783514464639706721250400288267372238950016114583259228262046633530468551311769574111763316146065958042194569102063373243372766692713192728878701004405568459288708477607744497502929764155046100964958011009313090462293046650352146796805866786767887226278836423536035611825593567576424943331337401071583562754098901412372708947790843318760718495117047155597276492717187936854356663665005157041552436478744491526494952982062613955349661409854888916015625");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+     
+    /**
+     * new BigDecimal(String value)
+     * when value is not a valid representation of BigDecimal.
+     */
+    public void testConstrStringException() {
+        String a = "-238768.787678287a+10";
+        try {
+            new BigDecimal(a);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {}
+    }
+
+    /**
+     * new BigDecimal(String value) when exponent is empty.
+     */
+    public void testConstrStringExceptionEmptyExponent1() {
+        String a = "-238768.787678287e";
+        try {
+            new BigDecimal(a);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+
+    /**
+     * new BigDecimal(String value) when exponent is empty.
+     */
+    public void testConstrStringExceptionEmptyExponent2() {
+        String a = "-238768.787678287e-";
+        try {
+            new BigDecimal(a);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+
+    /**
+     * new BigDecimal(String value) when exponent is greater than
+     * Integer.MAX_VALUE.
+     */
+    public void testConstrStringExceptionExponentGreaterIntegerMax() {
+        String a = "-238768.787678287e214748364767876";
+        try {
+            new BigDecimal(a);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+
+    /**
+     * new BigDecimal(String value) when exponent is less than
+     * Integer.MIN_VALUE.
+     */
+    public void testConstrStringExceptionExponentLessIntegerMin() {
+        String a = "-238768.787678287e-214748364767876";
+        try {
+            new BigDecimal(a);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+
+    /**
+     * new BigDecimal(String value)
+     * when exponent is Integer.MAX_VALUE.
+     */
+    public void testConstrStringExponentIntegerMax() {
+        String a = "-238768.787678287e2147483647";
+        int aScale = -2147483638;
+        BigInteger bA = new BigInteger("-238768787678287");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(String value)
+     * when exponent is Integer.MIN_VALUE.
+     */
+    public void testConstrStringExponentIntegerMin() {
+        String a = ".238768e-2147483648";
+        try {
+           new BigDecimal(a);
+           fail("NumberFormatException expected");
+       } catch (NumberFormatException e) {
+       }
+    }
+
+    /**
+     * new BigDecimal(String value); value does not contain exponent
+     */
+      public void testConstrStringWithoutExpPos1() {
+        String a = "732546982374982347892379283571094797.287346782359284756";
+        int aScale = 18;
+        BigInteger bA = new BigInteger("732546982374982347892379283571094797287346782359284756");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(String value); value does not contain exponent
+     */
+      public void testConstrStringWithoutExpPos2() {
+        String a = "+732546982374982347892379283571094797.287346782359284756";
+        int aScale = 18;
+        BigInteger bA = new BigInteger("732546982374982347892379283571094797287346782359284756");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+       
+    /**
+     * new BigDecimal(String value); value does not contain exponent
+     */
+      public void testConstrStringWithoutExpNeg() {
+        String a = "-732546982374982347892379283571094797.287346782359284756";
+        int aScale = 18;
+        BigInteger bA = new BigInteger("-732546982374982347892379283571094797287346782359284756");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+       
+    /**
+     * new BigDecimal(String value); value does not contain exponent
+     * and decimal point
+     */
+      public void testConstrStringWithoutExpWithoutPoint() {
+        String a = "-732546982374982347892379283571094797287346782359284756";
+        int aScale = 0;
+        BigInteger bA = new BigInteger("-732546982374982347892379283571094797287346782359284756");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+       
+      /**
+       * new BigDecimal(String value); value contains exponent
+       * and does not contain decimal point
+       */
+      public void testConstrStringWithExponentWithoutPoint1() {
+          String a = "-238768787678287e214";
+          int aScale = -214;
+          BigInteger bA = new BigInteger("-238768787678287");
+          BigDecimal aNumber = new BigDecimal(a);
+          assertEquals("incorrect value", bA, aNumber.unscaledValue());
+          assertEquals("incorrect scale", aScale, aNumber.scale());
+      }
+
+    /**
+     * new BigDecimal(String value); value contains exponent
+     * and does not contain decimal point
+     */
+    public void testConstrStringWithExponentWithoutPoint2() {
+        String a = "-238768787678287e-214";
+        int aScale = 214;
+        BigInteger bA = new BigInteger("-238768787678287");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+     
+    /**
+     * new BigDecimal(String value); value contains exponent
+     * and does not contain decimal point
+     */
+    public void testConstrStringWithExponentWithoutPoint3() {
+        String a = "238768787678287e-214";
+        int aScale = 214;
+        BigInteger bA = new BigInteger("238768787678287");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(String value); value contains exponent
+     * and does not contain decimal point
+     */
+    public void testConstrStringWithExponentWithoutPoint4() {
+        String a = "238768787678287e+214";
+        int aScale = -214;
+        BigInteger bA = new BigInteger("238768787678287");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(String value); value contains exponent
+     * and does not contain decimal point
+     */
+    public void testConstrStringWithExponentWithoutPoint5() {
+        String a = "238768787678287E214";
+        int aScale = -214;
+        BigInteger bA = new BigInteger("238768787678287");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(String value); 
+     * value contains both exponent and decimal point
+     */
+    public void testConstrStringWithExponentWithPoint1() {
+        String a = "23985439837984782435652424523876878.7678287e+214";
+        int aScale = -207;
+        BigInteger bA = new BigInteger("239854398379847824356524245238768787678287");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(String value); 
+     * value contains both exponent and decimal point
+     */
+    public void testConstrStringWithExponentWithPoint2() {
+        String a = "238096483923847545735673567457356356789029578490276878.7678287e-214";
+        int aScale = 221;
+        BigInteger bA = new BigInteger("2380964839238475457356735674573563567890295784902768787678287");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+
+    /**
+     * new BigDecimal(String value); 
+     * value contains both exponent and decimal point
+     */
+    public void testConstrStringWithExponentWithPoint3() {
+        String a = "2380964839238475457356735674573563567890.295784902768787678287E+21";
+        int aScale = 0;
+        BigInteger bA = new BigInteger("2380964839238475457356735674573563567890295784902768787678287");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+     
+    /**
+     * new BigDecimal(String value); 
+     * value contains both exponent and decimal point
+     */
+    public void testConstrStringWithExponentWithPoint4() {
+        String a = "23809648392384754573567356745735635678.90295784902768787678287E+21";
+        int aScale = 2;
+        BigInteger bA = new BigInteger("2380964839238475457356735674573563567890295784902768787678287");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+     
+    /**
+     * new BigDecimal(String value); 
+     * value contains both exponent and decimal point
+     */
+    public void testConstrStringWithExponentWithPoint5() {
+        String a = "238096483923847545735673567457356356789029.5784902768787678287E+21";
+        int aScale = -2;
+        BigInteger bA = new BigInteger("2380964839238475457356735674573563567890295784902768787678287");
+        BigDecimal aNumber = new BigDecimal(a);
+        assertEquals("incorrect value", bA, aNumber.unscaledValue());
+        assertEquals("incorrect scale", aScale, aNumber.scale());
+    }
+    
+    /**
+     * new BigDecimal(String value, MathContext)
+     */
+    public void testConstrStringMathContext() {
+        String a = "-238768787678287e214";
+        int precision = 5;
+        RoundingMode rm = RoundingMode.CEILING;
+        MathContext mc = new MathContext(precision, rm);
+        String res = "-23876";
+        int resScale = -224;
+        BigDecimal result = new BigDecimal(a, mc);
+        assertEquals("incorrect value", res, result.unscaledValue().toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConvertTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConvertTest.java
new file mode 100644
index 0000000..67fd8b4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConvertTest.java
@@ -0,0 +1,569 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * Class:  java.math.BigDecimal
+ * Methods: doubleValue, floatValue, intValue, longValue,  
+ * valueOf, toString, toBigInteger
+ */
+public class BigDecimalConvertTest extends TestCase {
+    /**
+     * Double value of a negative BigDecimal
+     */
+    public void testDoubleValueNeg() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        double result = -1.2380964839238476E53;
+        assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+    }
+
+    /**
+     * Double value of a positive BigDecimal
+     */
+    public void testDoubleValuePos() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        double result = 1.2380964839238476E53;
+        assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+    }
+
+    /**
+     * Double value of a large positive BigDecimal
+     */
+    public void testDoubleValuePosInfinity() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E+400";
+        BigDecimal aNumber = new BigDecimal(a);
+        double result = Double.POSITIVE_INFINITY;
+        assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+    }
+
+    /**
+     * Double value of a large negative BigDecimal
+     */
+    public void testDoubleValueNegInfinity() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E+400";
+        BigDecimal aNumber = new BigDecimal(a);
+        double result = Double.NEGATIVE_INFINITY;
+        assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+    }
+
+    /**
+     * Double value of a small negative BigDecimal
+     */
+    public void testDoubleValueMinusZero() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E-400";
+        BigDecimal aNumber = new BigDecimal(a);
+        long minusZero = -9223372036854775808L;
+        double result = aNumber.doubleValue();
+        assertTrue("incorrect value", Double.doubleToLongBits(result) == minusZero);
+    }
+
+    /**
+     * Double value of a small positive BigDecimal
+     */
+    public void testDoubleValuePlusZero() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E-400";
+        BigDecimal aNumber = new BigDecimal(a);
+        long zero = 0;
+        double result = aNumber.doubleValue();
+        assertTrue("incorrect value", Double.doubleToLongBits(result) == zero);
+    }
+
+    /**
+     * Float value of a negative BigDecimal
+     */
+    public void testFloatValueNeg() {
+        String a = "-1238096483923847.6356789029578E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        float result = -1.2380965E36F;
+        assertTrue("incorrect value", aNumber.floatValue() == result);
+    }
+
+    /**
+     * Float value of a positive BigDecimal
+     */
+    public void testFloatValuePos() {
+        String a = "1238096483923847.6356789029578E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        float result = 1.2380965E36F;
+        assertTrue("incorrect value", aNumber.floatValue() == result);
+    }
+
+    /**
+     * Float value of a large positive BigDecimal
+     */
+    public void testFloatValuePosInfinity() {
+        String a = "123809648373567356745735.6356789787678287E+200";
+        BigDecimal aNumber = new BigDecimal(a);
+        float result = Float.POSITIVE_INFINITY;
+        assertTrue("incorrect value", aNumber.floatValue() == result);
+    }
+
+    /**
+     * Float value of a large negative BigDecimal
+     */
+    public void testFloatValueNegInfinity() {
+        String a = "-123809648392384755735.63567887678287E+200";
+        BigDecimal aNumber = new BigDecimal(a);
+        float result = Float.NEGATIVE_INFINITY;
+        assertTrue("incorrect value", aNumber.floatValue() == result);
+    }
+
+    /**
+     * Float value of a small negative BigDecimal
+     */
+    public void testFloatValueMinusZero() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E-400";
+        BigDecimal aNumber = new BigDecimal(a);
+        int minusZero = -2147483648;
+        float result = aNumber.floatValue();
+        assertTrue("incorrect value", Float.floatToIntBits(result) == minusZero);
+    }
+
+    /**
+     * Float value of a small positive BigDecimal
+     */
+    public void testFloatValuePlusZero() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E-400";
+        BigDecimal aNumber = new BigDecimal(a);
+        int zero = 0;
+        float result = aNumber.floatValue();
+        assertTrue("incorrect value", Float.floatToIntBits(result) == zero);
+    }
+
+    /**
+     * Integer value of a negative BigDecimal
+     */
+    public void testIntValueNeg() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        int result = 218520473;
+        assertTrue("incorrect value", aNumber.intValue() == result);
+    }
+
+    /**
+     * Integer value of a positive BigDecimal
+     */
+    public void testIntValuePos() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        int result = -218520473;
+        assertTrue("incorrect value", aNumber.intValue() == result);
+    }
+
+    /**
+     * Long value of a negative BigDecimal
+     */
+    public void testLongValueNeg() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        long result = -1246043477766677607L;
+        assertTrue("incorrect value", aNumber.longValue() == result);
+    }
+
+    /**
+     * Long value of a positive BigDecimal
+     */
+    public void testLongValuePos() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigDecimal aNumber = new BigDecimal(a);
+        long result = 1246043477766677607L;
+        assertTrue("incorrect value", aNumber.longValue() == result);
+    }
+
+    /**
+     * scaleByPowerOfTen(int n)
+     */
+    public void testScaleByPowerOfTen1() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 13;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.scaleByPowerOfTen(10);
+        String res = "1231212478987482988429808779810457634781384756794.987";
+        int resScale = 3;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * scaleByPowerOfTen(int n)
+     */
+    public void testScaleByPowerOfTen2() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -13;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.scaleByPowerOfTen(10);
+        String res = "1.231212478987482988429808779810457634781384756794987E+74";
+        int resScale = -23;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Convert a positive BigDecimal to BigInteger
+     */
+    public void testToBigIntegerPos1() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigInteger bNumber = new BigInteger("123809648392384754573567356745735635678902957849027687");
+        BigDecimal aNumber = new BigDecimal(a);
+        BigInteger result = aNumber.toBigInteger();
+        assertTrue("incorrect value", result.equals(bNumber));
+    }
+
+    /**
+     * Convert a positive BigDecimal to BigInteger
+     */
+    public void testToBigIntegerPos2() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E+15";
+        BigInteger bNumber = new BigInteger("123809648392384754573567356745735635678902957849");
+        BigDecimal aNumber = new BigDecimal(a);
+        BigInteger result = aNumber.toBigInteger();
+        assertTrue("incorrect value", result.equals(bNumber));
+    }
+
+    /**
+     * Convert a positive BigDecimal to BigInteger
+     */
+    public void testToBigIntegerPos3() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E+45";
+        BigInteger bNumber = new BigInteger("123809648392384754573567356745735635678902957849027687876782870000000000000000");
+        BigDecimal aNumber = new BigDecimal(a);
+        BigInteger result = aNumber.toBigInteger();
+        assertTrue("incorrect value", result.equals(bNumber));
+    }
+
+    /**
+     * Convert a negative BigDecimal to BigInteger
+     */
+    public void testToBigIntegerNeg1() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+        BigInteger bNumber = new BigInteger("-123809648392384754573567356745735635678902957849027687");
+        BigDecimal aNumber = new BigDecimal(a);
+        BigInteger result = aNumber.toBigInteger();
+        assertTrue("incorrect value", result.equals(bNumber));
+    }
+
+    /**
+     * Convert a negative BigDecimal to BigInteger
+     */
+    public void testToBigIntegerNeg2() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E+15";
+        BigInteger bNumber = new BigInteger("-123809648392384754573567356745735635678902957849");
+        BigDecimal aNumber = new BigDecimal(a);
+        BigInteger result = aNumber.toBigInteger();
+        assertTrue("incorrect value", result.equals(bNumber));
+    }
+
+    /**
+     * Convert a negative BigDecimal to BigInteger
+     */
+    public void testToBigIntegerNeg3() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E+45";
+        BigInteger bNumber = new BigInteger("-123809648392384754573567356745735635678902957849027687876782870000000000000000");
+        BigDecimal aNumber = new BigDecimal(a);
+        BigInteger result = aNumber.toBigInteger();
+         assertTrue("incorrect value", result.equals(bNumber));
+    }
+
+    /**
+     * Convert a small BigDecimal to BigInteger
+     */
+    public void testToBigIntegerZero() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E-500";
+        BigInteger bNumber = new BigInteger("0");
+        BigDecimal aNumber = new BigDecimal(a);
+        BigInteger result = aNumber.toBigInteger();
+        assertTrue("incorrect value", result.equals(bNumber));
+    }
+
+    /**
+     * toBigIntegerExact()
+     */
+    public void testToBigIntegerExact1() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E+45";
+        BigDecimal aNumber = new BigDecimal(a);
+        String res = "-123809648392384754573567356745735635678902957849027687876782870000000000000000";
+        BigInteger result = aNumber.toBigIntegerExact();
+        assertEquals("incorrect value", res, result.toString());
+    }
+
+    /**
+     * toBigIntegerExact()
+     */
+    public void testToBigIntegerExactException() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E-10";
+        BigDecimal aNumber = new BigDecimal(a);
+        try {
+            aNumber.toBigIntegerExact();
+            fail("java.lang.ArithmeticException has not been thrown");
+        } catch (java.lang.ArithmeticException e) {
+            return;
+        }
+    }
+
+    /**
+     * Convert a positive BigDecimal to an engineering string representation
+     */
+    public void testToEngineeringStringPos() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E-501";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "123.80964839238475457356735674573563567890295784902768787678287E-471";
+        assertEquals("incorrect value", result, aNumber.toEngineeringString());
+    }
+
+    /**
+     * Convert a negative BigDecimal to an engineering string representation
+     */
+    public void testToEngineeringStringNeg() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E-501";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "-123.80964839238475457356735674573563567890295784902768787678287E-471";
+        assertEquals("incorrect value", result, aNumber.toEngineeringString());
+    }
+
+    /**
+     * Convert a negative BigDecimal to an engineering string representation
+     */
+    public void testToEngineeringStringZeroPosExponent() {
+        String a = "0.0E+16";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "0E+15";
+        assertEquals("incorrect value", result, aNumber.toEngineeringString());
+    }
+
+    /**
+     * Convert a negative BigDecimal to an engineering string representation
+     */
+    public void testToEngineeringStringZeroNegExponent() {
+        String a = "0.0E-16";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "0.00E-15";
+        assertEquals("incorrect value", result, aNumber.toEngineeringString());
+    }
+
+    /**
+     * Convert a negative BigDecimal with a negative exponent to a plain string
+     * representation; scale == 0.
+     */
+     public void testToPlainStringNegNegExp() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E-100";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "-0.000000000000000000000000000000000000000000000000000000000000000000012380964839238475457356735674573563567890295784902768787678287";
+        assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+    }
+
+    /**
+     * Convert a negative BigDecimal with a positive exponent
+     * to a plain string representation;
+     * scale == 0.
+     */
+     public void testToPlainStringNegPosExp() {
+        String a = "-123809648392384754573567356745735.63567890295784902768787678287E100";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "-1238096483923847545735673567457356356789029578490276878767828700000000000000000000000000000000000000000000000000000000000000000000000";
+        assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+    }
+
+    /**
+     * Convert a positive BigDecimal with a negative exponent
+     * to a plain string representation;
+     * scale == 0.
+     */
+     public void testToPlainStringPosNegExp() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E-100";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "0.000000000000000000000000000000000000000000000000000000000000000000012380964839238475457356735674573563567890295784902768787678287";
+        assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+    }
+
+    /**
+     * Convert a negative BigDecimal with a negative exponent
+     * to a plain string representation;
+     * scale == 0.
+     */
+     public void testToPlainStringPosPosExp() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E+100";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "1238096483923847545735673567457356356789029578490276878767828700000000000000000000000000000000000000000000000000000000000000000000000";
+        assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+    }
+
+    /**
+     * Convert a BigDecimal to a string representation;
+     * scale == 0.
+     */
+     public void testToStringZeroScale() {
+        String a = "-123809648392384754573567356745735635678902957849027687876782870";
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a));
+        String result = "-123809648392384754573567356745735635678902957849027687876782870";
+        assertTrue("incorrect value", aNumber.toString().equals(result));
+    }
+
+    /**
+     * Convert a positive BigDecimal to a string representation
+     */
+    public void testToStringPos() {
+        String a = "123809648392384754573567356745735.63567890295784902768787678287E-500";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "1.2380964839238475457356735674573563567890295784902768787678287E-468";
+        assertTrue("incorrect value", aNumber.toString().equals(result));
+    }
+
+    /**
+     * Convert a negative BigDecimal to a string representation
+     */
+    public void testToStringNeg() {
+        String a = "-123.4564563673567380964839238475457356735674573563567890295784902768787678287E-5";
+        BigDecimal aNumber = new BigDecimal(a);
+        String result = "-0.001234564563673567380964839238475457356735674573563567890295784902768787678287";
+        assertTrue("incorrect value", aNumber.toString().equals(result));
+    }
+
+    /**
+     * Create a BigDecimal from a positive long value; scale == 0
+     */
+    public void testValueOfPosZeroScale() {
+        long a = 98374823947823578L;
+        BigDecimal aNumber = BigDecimal.valueOf(a);
+        String result = "98374823947823578";
+        assertTrue("incorrect value", aNumber.toString().equals(result));
+    }
+
+    /**
+     * Create a BigDecimal from a negative long value; scale is 0
+     */
+    public void testValueOfNegZeroScale() {
+        long a = -98374823947823578L;
+        BigDecimal aNumber = BigDecimal.valueOf(a);
+        String result = "-98374823947823578";
+        assertTrue("incorrect value", aNumber.toString().equals(result));
+    }
+
+    /**
+     * Create a BigDecimal from a negative long value; scale is positive
+     */
+    public void testValueOfNegScalePos() {
+        long a = -98374823947823578L;
+        int scale = 12;
+        BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+        String result = "-98374.823947823578";
+        assertTrue("incorrect value", aNumber.toString().equals(result));
+    }
+
+    /**
+     * Create a BigDecimal from a negative long value; scale is negative
+     */
+    public void testValueOfNegScaleNeg() {
+        long a = -98374823947823578L;
+        int scale = -12;
+        BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+        String result = "-9.8374823947823578E+28";
+        assertTrue("incorrect value", aNumber.toString().equals(result));
+    }
+
+    /**
+     * Create a BigDecimal from a negative long value; scale is positive
+     */
+    public void testValueOfPosScalePos() {
+        long a = 98374823947823578L;
+        int scale = 12;
+        BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+        String result = "98374.823947823578";
+        assertTrue("incorrect value", aNumber.toString().equals(result));
+    }
+
+    /**
+     * Create a BigDecimal from a negative long value; scale is negative
+     */
+    public void testValueOfPosScaleNeg() {
+        long a = 98374823947823578L;
+        int scale = -12;
+        BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+        String result = "9.8374823947823578E+28";
+        assertTrue("incorrect value", aNumber.toString().equals(result));
+    }
+
+    /**
+     * Create a BigDecimal from a negative double value
+     */
+    public void testValueOfDoubleNeg() {
+        double a = -65678765876567576.98788767;
+        BigDecimal result = BigDecimal.valueOf(a);
+        String res = "-65678765876567576";
+        int resScale = 0;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Create a BigDecimal from a positive double value
+     */
+    public void testValueOfDoublePos1() {
+        double a = 65678765876567576.98788767;
+        BigDecimal result = BigDecimal.valueOf(a);
+        String res = "65678765876567576";
+        int resScale = 0;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Create a BigDecimal from a positive double value
+     */
+    public void testValueOfDoublePos2() {
+        double a = 12321237576.98788767;
+        BigDecimal result = BigDecimal.valueOf(a);
+        String res = "12321237576.987888";
+        int resScale = 6;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * Create a BigDecimal from a positive double value
+     */
+    public void testValueOfDoublePos3() {
+        double a = 12321237576.9878838;
+        BigDecimal result = BigDecimal.valueOf(a);
+        String res = "12321237576.987885";
+        int resScale = 6;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+
+    /**
+     * valueOf(Double.NaN)
+     */
+    public void testValueOfDoubleNaN() {
+        double a = Double.NaN;
+        try {
+            BigDecimal.valueOf(a);
+            fail("NumberFormatException has not been thrown for Double.NaN");
+        } catch (NumberFormatException e) {
+            return;
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalScaleOperationsTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalScaleOperationsTest.java
new file mode 100644
index 0000000..6c74dee
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalScaleOperationsTest.java
@@ -0,0 +1,348 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.*;
+
+/**
+ * Class:  java.math.BigDecimal
+ * Methods: movePointLeft, movePointRight, scale, setScale, unscaledValue * 
+ */
+public class BigDecimalScaleOperationsTest extends TestCase {
+    /**
+     * Check the default scale
+     */
+    public void testScaleDefault() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int cScale = 0;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a));
+        assertTrue("incorrect scale", aNumber.scale() == cScale);
+    }
+
+    /**
+     * Check a negative scale
+     */
+    public void testScaleNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = -10;
+        int cScale = -10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        assertTrue("incorrect scale", aNumber.scale() == cScale);
+    }
+
+    /**
+     * Check a positive scale
+     */
+    public void testScalePos() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 10;
+        int cScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        assertTrue("incorrect scale", aNumber.scale() == cScale);
+    }
+
+    /**
+     * Check the zero scale
+     */
+    public void testScaleZero() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 0;
+        int cScale = 0;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        assertTrue("incorrect scale", aNumber.scale() == cScale);
+    }
+
+    /**
+     * Check the unscaled value
+     */
+    public void testUnscaledValue() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 100;
+        BigInteger bNumber = new BigInteger(a);
+        BigDecimal aNumber = new BigDecimal(bNumber, aScale);
+        assertTrue("incorrect unscaled value", aNumber.unscaledValue().equals(bNumber));
+    }
+    
+    /**
+     * Set a greater new scale
+     */
+    public void testSetScaleGreater() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 18;
+        int newScale = 28;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.setScale(newScale);
+        assertTrue("incorrect scale", bNumber.scale() == newScale);
+        assertEquals("incorrect value", 0, bNumber.compareTo(aNumber));
+    }
+
+    /**
+     * Set a less new scale; this.scale == 8; newScale == 5.
+     */
+    public void testSetScaleLess() {
+        String a = "2.345726458768760000E+10";
+        int newScale = 5;
+        BigDecimal aNumber = new BigDecimal(a);
+        BigDecimal bNumber = aNumber.setScale(newScale);
+        assertTrue("incorrect scale", bNumber.scale() == newScale);
+        assertEquals("incorrect value", 0, bNumber.compareTo(aNumber));
+    }
+
+    /**
+     * Verify an exception when setting a new scale
+     */
+    public void testSetScaleException() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 28;
+        int newScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        try {
+            aNumber.setScale(newScale);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+            assertEquals("Improper exception message", "Rounding necessary", e.getMessage());
+        }
+    }
+
+    /**
+     * Set the same new scale
+     */
+    public void testSetScaleSame() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 18;
+        int newScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.setScale(newScale);
+        assertTrue("incorrect scale", bNumber.scale() == newScale);
+        assertTrue("incorrect value", bNumber.equals(aNumber));
+    }
+
+    /**
+     * Set a new scale
+     */
+    public void testSetScaleRoundUp() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        String b = "123121247898748298842980877981045763478139";
+        int aScale = 28;
+        int newScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_UP);
+        assertTrue("incorrect scale", bNumber.scale() == newScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+    }
+
+    /**
+     * Set a new scale
+     */
+    public void testSetScaleRoundDown() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        String b = "123121247898748298842980877981045763478138";
+        int aScale = 28;
+        int newScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_DOWN);
+        assertTrue("incorrect scale", bNumber.scale() == newScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+    }
+
+    /**
+     * Set a new scale
+     */
+    public void testSetScaleRoundCeiling() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        String b = "123121247898748298842980877981045763478139";
+        int aScale = 28;
+        int newScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_CEILING);
+        assertTrue("incorrect scale", bNumber.scale() == newScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+    }
+
+    /**
+     * Set a new scale
+     */
+    public void testSetScaleRoundFloor() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        String b = "123121247898748298842980877981045763478138";
+        int aScale = 28;
+        int newScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_FLOOR);
+        assertTrue("incorrect scale", bNumber.scale() == newScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+    }
+
+    /**
+     * Set a new scale
+     */
+    public void testSetScaleRoundHalfUp() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        String b = "123121247898748298842980877981045763478138";
+        int aScale = 28;
+        int newScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_HALF_UP);
+        assertTrue("incorrect scale", bNumber.scale() == newScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+    }
+
+    /**
+     * Set a new scale
+     */
+    public void testSetScaleRoundHalfDown() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        String b = "123121247898748298842980877981045763478138";
+        int aScale = 28;
+        int newScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_HALF_DOWN);
+        assertTrue("incorrect scale", bNumber.scale() == newScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+    }
+
+    /**
+     * Set a new scale
+     */
+    public void testSetScaleRoundHalfEven() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        String b = "123121247898748298842980877981045763478138";
+        int aScale = 28;
+        int newScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_HALF_EVEN);
+        assertTrue("incorrect scale", bNumber.scale() == newScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+    }
+    
+    /**
+     * SetScale(int, RoundingMode)
+     */
+    public void testSetScaleIntRoundingMode() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 28;
+        int newScale = 18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal result = aNumber.setScale(newScale, RoundingMode.HALF_EVEN);
+        String res = "123121247898748298842980.877981045763478138";
+        int resScale = 18;
+        assertEquals("incorrect value", res, result.toString());
+        assertEquals("incorrect scale", resScale, result.scale());
+    }
+    
+    /**
+     * Move the decimal point to the left; the shift value is positive
+     */
+    public void testMovePointLeftPos() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 28;
+        int shift = 18;
+        int resScale = 46;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.movePointLeft(shift);
+        assertTrue("incorrect scale", bNumber.scale() == resScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+    }
+        
+    /**
+     * Move the decimal point to the left; the shift value is positive
+     */
+    public void testMovePointLeftNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 28;
+        int shift = -18;
+        int resScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.movePointLeft(shift);
+        assertTrue("incorrect scale", bNumber.scale() == resScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+    }
+
+    /**
+     * Move the decimal point to the right; the shift value is positive
+     */
+    public void testMovePointRightPosGreater() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 28;
+        int shift = 18;
+        int resScale = 10;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.movePointRight(shift);
+        assertTrue("incorrect scale", bNumber.scale() == resScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+    }
+        
+    /**
+     * Move the decimal point to the right; the shift value is positive
+     */
+    public void testMovePointRightPosLess() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        String b = "123121247898748298842980877981045763478138475679498700";
+        int aScale = 28;
+        int shift = 30;
+        int resScale = 0;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.movePointRight(shift);
+        assertTrue("incorrect scale", bNumber.scale() == resScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+    }
+        
+    /**
+     * Move the decimal point to the right; the shift value is positive
+     */
+    public void testMovePointRightNeg() {
+        String a = "1231212478987482988429808779810457634781384756794987";
+        int aScale = 28;
+        int shift = -18;
+        int resScale = 46;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        BigDecimal bNumber = aNumber.movePointRight(shift);
+        assertTrue("incorrect scale", bNumber.scale() == resScale);
+        assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+    }
+
+    /**
+     * Move the decimal point to the right when the scale overflows
+     */
+    public void testMovePointRightException() {
+        String a = "12312124789874829887348723648726347429808779810457634781384756794987";
+        int aScale = Integer.MAX_VALUE; //2147483647
+        int shift = -18;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        try {
+            aNumber.movePointRight(shift);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+        }
+    }
+
+    /**
+     * precision()
+     */
+    public void testPrecision() {
+        String a = "12312124789874829887348723648726347429808779810457634781384756794987";
+        int aScale = 14;
+        BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+        int prec = aNumber.precision();
+        assertEquals(68, prec);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAddTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAddTest.java
new file mode 100644
index 0000000..913eb8a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAddTest.java
@@ -0,0 +1,495 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:  java.math.BigInteger
+ * Method: add 
+ */
+public class BigIntegerAddTest extends TestCase {
+    /**
+     * Add two positive numbers of the same length
+     */
+    public void testCase1() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {11, 22, 33, 44, 55, 66, 77, 11, 22, 33};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Add two negative numbers of the same length
+     */
+    public void testCase2() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-12, -23, -34, -45, -56, -67, -78, -12, -23, -33};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Add two numbers of the same length.
+     * The first one is positive and the second is negative.
+     * The first one is greater in absolute value.
+     */
+    public void testCase3() {
+        byte aBytes[] = {3, 4, 5, 6, 7, 8, 9};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte rBytes[] = {2, 2, 2, 2, 2, 2, 2};
+        int aSign = 1;
+        int bSign = -1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Add two numbers of the same length.
+     * The first one is negative and the second is positive.
+     * The first one is greater in absolute value.
+     */
+    public void testCase4() {
+        byte aBytes[] = {3, 4, 5, 6, 7, 8, 9};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte rBytes[] = {-3, -3, -3, -3, -3, -3, -2};
+        int aSign = -1;
+        int bSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Add two numbers of the same length.
+     * The first is positive and the second is negative.
+     * The first is less in absolute value.
+     */
+    public void testCase5() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {3, 4, 5, 6, 7, 8, 9};
+        byte rBytes[] = {-3, -3, -3, -3, -3, -3, -2};
+        int aSign = 1;
+        int bSign = -1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Add two numbers of the same length.
+     * The first one is negative and the second is positive.
+     * The first one is less in absolute value.
+     */
+    public void testCase6() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {3, 4, 5, 6, 7, 8, 9};
+        byte rBytes[] = {2, 2, 2, 2, 2, 2, 2};
+        int aSign = -1;
+        int bSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Add two positive numbers of different length.
+     * The first is longer.
+     */
+    public void testCase7() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Add two positive numbers of different length.
+     * The second is longer.
+     */
+    public void testCase8() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+        BigInteger aNumber = new BigInteger(aBytes);
+        BigInteger bNumber = new BigInteger(bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Add two negative numbers of different length.
+     * The first is longer.
+     */
+    public void testCase9() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Add two negative numbers of different length.
+     * The second is longer.
+     */
+    public void testCase10() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Add two numbers of different length and sign.
+     * The first is positive.
+     * The first is longer.
+     */
+    public void testCase11() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Add two numbers of different length and sign.
+     * The first is positive.
+     * The second is longer.
+     */
+    public void testCase12() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Add two numbers of different length and sign.
+     * The first is negative.
+     * The first is longer.
+     */
+    public void testCase13() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Add two numbers of different length and sign.
+     * The first is negative.
+     * The second is longer.
+     */
+    public void testCase14() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * Add two equal numbers of different signs
+     */
+    public void testCase15() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte rBytes[] = {0};
+        int aSign = -1;
+        int bSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * Add zero to a number
+     */
+    public void testCase16() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {0};
+        byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        int aSign = 1;
+        int bSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Add a number to zero
+     */
+    public void testCase17() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        int aSign = 1;
+        int bSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * Add zero to zero
+     */
+    public void testCase18() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {0};
+        byte rBytes[] = {0};
+        int aSign = 1;
+        int bSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+    
+    /**
+     * Add ZERO to a number
+     */
+    public void testCase19() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        int aSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ZERO;
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Add a number to zero
+     */
+    public void testCase20() {
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        int bSign = 1;
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * Add ZERO to ZERO
+     */
+    public void testCase21() {
+        byte rBytes[] = {0};
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger bNumber = BigInteger.ZERO;
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * Add ONE to ONE
+     */
+    public void testCase22() {
+        byte rBytes[] = {2};
+        BigInteger aNumber = BigInteger.ONE;
+        BigInteger bNumber = BigInteger.ONE;
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Add two numbers so that carry is 1
+     */
+    public void testCase23() {
+        byte aBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+        byte bBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+        int aSign = 1;
+        int bSign = 1;
+        byte rBytes[] = {1, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -2};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.add(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAndTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAndTest.java
new file mode 100644
index 0000000..d057bfa
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAndTest.java
@@ -0,0 +1,432 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:  java.math.BigInteger
+ * Method: and 
+ */
+public class BigIntegerAndTest extends TestCase {
+    /**
+     * And for zero and a positive number
+     */
+    public void testZeroPos() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 0;
+        int bSign = 1;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * And for zero and a negative number
+     */
+    public void testZeroNeg() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 0;
+        int bSign = -1;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * And for a positive number and zero 
+     */
+    public void testPosZero() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {0};
+        int aSign = 1;
+        int bSign = 0;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * And for a negative number and zero  
+     */
+    public void testNegPos() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {0};
+        int aSign = -1;
+        int bSign = 0;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * And for zero and zero
+     */
+    public void testZeroZero() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {0};
+        int aSign = 0;
+        int bSign = 0;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * And for zero and one
+     */
+    public void testZeroOne() {
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger bNumber = BigInteger.ONE;
+        BigInteger result = aNumber.and(bNumber);
+        assertTrue(result.equals(BigInteger.ZERO));
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * And for one and one
+     */
+    public void testOneOne() {
+        BigInteger aNumber = BigInteger.ONE;
+        BigInteger bNumber = BigInteger.ONE;
+        BigInteger result = aNumber.and(bNumber);
+        assertTrue(result.equals(BigInteger.ONE));
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * And for two positive numbers of the same length
+     */
+    public void testPosPosSameLength() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -128, 56, 100, 4, 4, 17, 37, 16, 1, 64, 1, 10, 3};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * And for two positive numbers; the first is longer
+     */
+    public void testPosPosFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -2, -76, 88, 44, 1, 2, 17, 35, 16, 9, 2, 5, 6, 21};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * And for two positive numbers; the first is shorter
+     */
+    public void testPosPosFirstShorter() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -2, -76, 88, 44, 1, 2, 17, 35, 16, 9, 2, 5, 6, 21};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * And for two negative numbers of the same length
+     */
+    public void testNegNegSameLength() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-1, 1, 2, 3, 3, 0, 65, -96, -48, -124, -60, 12, -40, -31, 97};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * And for two negative numbers; the first is longer
+     */
+    public void testNegNegFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-1, 127, -10, -57, -101, 1, 2, 2, 2, -96, -16, 8, -40, -59, 68, -88, -88, 16, 73};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * And for two negative numbers; the first is shorter
+     */
+    public void testNegNegFirstShorter() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-1, 127, -10, -57, -101, 1, 2, 2, 2, -96, -16, 8, -40, -59, 68, -88, -88, 16, 73};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * And for two numbers of different signs and the same length
+     */
+    public void testPosNegSameLength() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {0, -6, -80, 72, 8, 75, 2, -79, 34, 16, -119};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * And for two numbers of different signs and the same length
+     */
+    public void testNegPosSameLength() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -2, 125, -60, -104, 1, 10, 6, 2, 32, 56, 2, 4, 4, 21};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * And for a negative and a positive numbers; the first is longer
+     */
+    public void testNegPosFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 3};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * And for a negative and a positive numbers; the first is shorter
+     */
+    public void testNegPosFirstShorter() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -128, 9, 56, 100, 0, 0, 1, 1, 90, 1, -32, 0, 10, -126, 21, 82, -31, -95};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * And for a positive and a negative numbers; the first is longer
+     */
+    public void testPosNegFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {0, -128, 9, 56, 100, 0, 0, 1, 1, 90, 1, -32, 0, 10, -126, 21, 82, -31, -95};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * And for a positive and a negative numbers; the first is shorter
+     */
+    public void testPosNegFirstShorter() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 3};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Test for a special case
+     */
+    public void testSpecialCase1() {
+        byte aBytes[] = {-1, -1, -1, -1};
+        byte bBytes[] = {5, -4, -3, -2};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-1, 0, 0, 0, 0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Test for a special case
+     */
+    public void testSpecialCase2() {
+        byte aBytes[] = {-51};
+        byte bBytes[] = {-52, -51, -50, -49, -48};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -52, -51, -50, -49, 16};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.and(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerCompareTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerCompareTest.java
new file mode 100644
index 0000000..a65c77e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerCompareTest.java
@@ -0,0 +1,533 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:   java.math.BigInteger
+ * Methods: abs, compareTo, equals, max, min, negate, signum
+ */
+public class BigIntegerCompareTest extends TestCase {
+    /**
+     * abs() for a positive number
+     */
+    public void testAbsPositive() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        int aSign = 1;
+        byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.abs();
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * abs() for a negative number
+     */
+    public void testAbsNegative() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        int aSign = -1;
+        byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.abs();
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * compareTo(BigInteger a).
+     * Compare two positive numbers.
+     * The first is greater.
+     */
+    public void testCompareToPosPos1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = 1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        assertEquals(1, aNumber.compareTo(bNumber));
+    }
+    
+    /**
+     * compareTo(BigInteger a).
+     * Compare two positive numbers.
+     * The first is less.
+     */
+    public void testCompareToPosPos2() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        int bSign = 1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        assertEquals(-1, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * compareTo(BigInteger a).
+     * Compare two equal positive numbers.
+     */
+    public void testCompareToEqualPos() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        int bSign = 1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        assertEquals(0, aNumber.compareTo(bNumber));
+    }
+    
+    /**
+     * compareTo(BigInteger a).
+     * Compare two negative numbers.
+     * The first is greater in absolute value.
+     */
+    public void testCompareToNegNeg1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = -1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        assertEquals(-1, aNumber.compareTo(bNumber));
+    }
+    
+    /**
+     * compareTo(BigInteger a).
+     * Compare two negative numbers.
+     * The first is less  in absolute value.
+     */
+    public void testCompareNegNeg2() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = -1;
+        int bSign = -1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        assertEquals(1, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * compareTo(BigInteger a).
+     * Compare two equal negative numbers.
+     */
+    public void testCompareToEqualNeg() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = -1;
+        int bSign = -1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        assertEquals(0, aNumber.compareTo(bNumber));
+    }
+    
+    /**
+     * compareTo(BigInteger a).
+     * Compare two numbers of different signs.
+     * The first is positive.
+     */
+    public void testCompareToDiffSigns1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = -1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        assertEquals(1, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * compareTo(BigInteger a).
+     * Compare two numbers of different signs.
+     * The first is negative.
+     */
+    public void testCompareToDiffSigns2() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = 1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        assertEquals(-1, aNumber.compareTo(bNumber));
+    }
+    
+    /**
+     * compareTo(BigInteger a).
+     * Compare a positive number to ZERO.
+     */
+    public void testCompareToPosZero() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ZERO;
+        assertEquals(1, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * compareTo(BigInteger a).
+     * Compare ZERO to a positive number.
+     */
+    public void testCompareToZeroPos() {
+        byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int bSign = 1;
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        assertEquals(-1, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * compareTo(BigInteger a).
+     * Compare a negative number to ZERO.
+     */
+    public void testCompareToNegZero() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = -1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ZERO;
+        assertEquals(-1, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * compareTo(BigInteger a).
+     * Compare ZERO to a negative number.
+     */
+    public void testCompareToZeroNeg() {
+        byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int bSign = -1;
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        assertEquals(1, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * compareTo(BigInteger a).
+     * Compare ZERO to ZERO.
+     */
+    public void testCompareToZeroZero() {
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger bNumber = BigInteger.ZERO;
+        assertEquals(0, aNumber.compareTo(bNumber));
+    }
+
+    /**
+     * equals(Object obj).
+     * obj is not a BigInteger
+     */
+    public void testEqualsObject() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        Object obj = new Object();
+        assertFalse(aNumber.equals(obj));
+    }
+
+    /**
+     * equals(null).
+     */
+    public void testEqualsNull() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertFalse(aNumber.equals(null));
+    }
+
+    /**
+     * equals(Object obj).
+     * obj is a BigInteger.
+     * numbers are equal.
+     */
+    public void testEqualsBigIntegerTrue() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        int bSign = 1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        Object bNumber = new BigInteger(bSign, bBytes);
+        assertTrue(aNumber.equals(bNumber));
+    }
+
+    /**
+     * equals(Object obj).
+     * obj is a BigInteger.
+     * numbers are not equal.
+     */
+    public void testEqualsBigIntegerFalse() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        int bSign = 1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        Object bNumber = new BigInteger(bSign, bBytes);
+        assertFalse(aNumber.equals(bNumber));
+    }
+
+    /**
+     * max(BigInteger val).
+     * the first is greater.
+     */
+    public void testMaxGreater() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.max(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertTrue("incorrect sign", result.signum() == 1);
+    }
+
+    /**
+     * max(BigInteger val).
+     * the first is less.
+     */
+    public void testMaxLess() {
+        byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.max(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertTrue("incorrect sign", result.signum() == 1);
+    }
+
+    /**
+     * max(BigInteger val).
+     * numbers are equal.
+     */
+    public void testMaxEqual() {
+        byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.max(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * max(BigInteger val).
+     * max of negative and ZERO.
+     */
+    public void testMaxNegZero() {
+        byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = -1;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ZERO;
+        BigInteger result = aNumber.max(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertTrue("incorrect sign", result.signum() == 0);
+    }
+
+    /**
+     * min(BigInteger val).
+     * the first is greater.
+     */
+    public void testMinGreater() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.min(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * min(BigInteger val).
+     * the first is less.
+     */
+    public void testMinLess() {
+        byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.min(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * min(BigInteger val).
+     * numbers are equal.
+     */
+    public void testMinEqual() {
+        byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.min(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertTrue("incorrect sign", result.signum() == 1);
+    }
+
+    /**
+     * max(BigInteger val).
+     * min of positive and ZERO.
+     */
+    public void testMinPosZero() {
+        byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ZERO;
+        BigInteger result = aNumber.min(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertTrue("incorrect sign", result.signum() == 0);
+    }
+    
+    /**
+     * negate() a positive number.
+     */
+    public void testNegatePositive() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        byte rBytes[] = {-13, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -27, -4, -91};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.negate();
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertTrue("incorrect sign", result.signum() == -1);
+    }
+
+    /**
+     * negate() a negative number.
+     */
+    public void testNegateNegative() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = -1;
+        byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.negate();
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertTrue("incorrect sign", result.signum() == 1);
+    }
+
+    /**
+     * negate() ZERO.
+     */
+    public void testNegateZero() {
+        byte rBytes[] = {0};
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger result = aNumber.negate();
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }    
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * signum() of a positive number.
+     */
+    public void testSignumPositive() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+    
+    /**
+     * signum() of a negative number.
+     */
+    public void testSignumNegative() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = -1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+    
+    /**
+     * signum() of ZERO.
+     */
+    public void testSignumZero() {
+        BigInteger aNumber = BigInteger.ZERO;
+        assertEquals("incorrect sign", 0, aNumber.signum());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConstructorsTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConstructorsTest.java
new file mode 100644
index 0000000..1e0e4a1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConstructorsTest.java
@@ -0,0 +1,786 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+import java.util.Random;
+
+/**
+ * Class:   java.math.BigInteger
+ * Constructors: BigInteger(byte[] a), BigInteger(int sign, byte[] a), 
+ *               BigInteger(String val, int radix)
+ */
+public class BigIntegerConstructorsTest extends TestCase {
+    /**
+     * Create a number from an array of bytes.
+     * Verify an exception thrown if an array is zero bytes long
+     */
+    public void testConstructorBytesException() {
+        byte aBytes[] = {};
+        try {
+            new BigInteger(aBytes);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+    
+    /**
+     * Create a positive number from an array of bytes.
+     * The number fits in an array of integers.
+     */
+    public void testConstructorBytesPositive1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        BigInteger aNumber = new BigInteger(aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a positive number from an array of bytes.
+     * The number fits in an integer.
+     */
+    public void testConstructorBytesPositive2() {
+        byte aBytes[] = {12, 56, 100};
+        byte rBytes[] = {12, 56, 100};
+        BigInteger aNumber = new BigInteger(aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a positive number from an array of bytes.
+     * The number of bytes is 4.
+     */
+    public void testConstructorBytesPositive3() {
+        byte aBytes[] = {127, 56, 100, -1};
+        byte rBytes[] = {127, 56, 100, -1};
+        BigInteger aNumber = new BigInteger(aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a positive number from an array of bytes.
+     * The number of bytes is multiple of 4.
+     */
+    public void testConstructorBytesPositive() {
+        byte aBytes[] = {127, 56, 100, -1, 14, 75, -24, -100};
+        byte rBytes[] = {127, 56, 100, -1, 14, 75, -24, -100};
+        BigInteger aNumber = new BigInteger(aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a negative number from an array of bytes.
+     * The number fits in an array of integers.
+     */
+    public void testConstructorBytesNegative1() {
+        byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        byte rBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        BigInteger aNumber = new BigInteger(aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * Create a negative number from an array of bytes.
+     * The number fits in an integer.
+     */
+    public void testConstructorBytesNegative2() {
+        byte aBytes[] = {-12, 56, 100};
+        byte rBytes[] = {-12, 56, 100};
+        BigInteger aNumber = new BigInteger(aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * Create a negative number from an array of bytes.
+     * The number of bytes is 4.
+     */
+    public void testConstructorBytesNegative3() {
+        byte aBytes[] = {-128, -12, 56, 100};
+        byte rBytes[] = {-128, -12, 56, 100};
+        BigInteger aNumber = new BigInteger(aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+    
+    /**
+     * Create a negative number from an array of bytes.
+     * The number of bytes is multiple of 4.
+     */
+    public void testConstructorBytesNegative4() {
+        byte aBytes[] = {-128, -12, 56, 100, -13, 56, 93, -78};
+        byte rBytes[] = {-128, -12, 56, 100, -13, 56, 93, -78};
+        BigInteger aNumber = new BigInteger(aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * Create a zero number from an array of zero bytes.
+     */
+    public void testConstructorBytesZero() {
+        byte aBytes[] = {0, 0, 0, -0, +0, 0, -0};
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, aNumber.signum());
+    }
+
+    /**
+     * Create a number from a sign and an array of bytes.
+     * Verify an exception thrown if a sign has improper value.
+     */
+    public void testConstructorSignBytesException1() {
+        byte aBytes[] = {123, 45, -3, -76};
+        int aSign = 3;
+        try {
+            new BigInteger(aSign, aBytes);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+    
+    /**
+     * Create a number from a sign and an array of bytes.
+     * Verify an exception thrown if the array contains non-zero bytes while the sign is 0. 
+     */
+    public void testConstructorSignBytesException2() {
+        byte aBytes[] = {123, 45, -3, -76};
+        int aSign = 0;
+        try {
+            new BigInteger(aSign, aBytes);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+            assertEquals("Improper exception message", "signum-magnitude mismatch", e.getMessage());
+        }
+    }
+
+    /**
+     * Create a positive number from a sign and an array of bytes.
+     * The number fits in an array of integers.
+     * The most significant byte is positive.
+     */
+    public void testConstructorSignBytesPositive1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+        int aSign = 1;
+        byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+    
+    /**
+     * Create a positive number from a sign and an array of bytes.
+     * The number fits in an array of integers.
+     * The most significant byte is negative.
+     */
+    public void testConstructorSignBytesPositive2() {
+        byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+        int aSign = 1;
+        byte rBytes[] = {0, -12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a positive number from a sign and an array of bytes.
+     * The number fits in an integer.
+     */
+    public void testConstructorSignBytesPositive3() {
+        byte aBytes[] = {-12, 56, 100};
+        int aSign = 1;
+        byte rBytes[] = {0, -12, 56, 100};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a positive number from a sign and an array of bytes.
+     * The number of bytes is 4.
+     * The most significant byte is positive.
+     */
+    public void testConstructorSignBytesPositive4() {
+        byte aBytes[] = {127, 56, 100, -2};
+        int aSign = 1;
+        byte rBytes[] = {127, 56, 100, -2};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a positive number from a sign and an array of bytes.
+     * The number of bytes is 4.
+     * The most significant byte is negative.
+     */
+    public void testConstructorSignBytesPositive5() {
+        byte aBytes[] = {-127, 56, 100, -2};
+        int aSign = 1;
+        byte rBytes[] = {0, -127, 56, 100, -2};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+    
+    /**
+     * Create a positive number from a sign and an array of bytes.
+     * The number of bytes is multiple of 4.
+     * The most significant byte is positive.
+     */
+    public void testConstructorSignBytesPositive6() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+        int aSign = 1;
+        byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a positive number from a sign and an array of bytes.
+     * The number of bytes is multiple of 4.
+     * The most significant byte is negative.
+     */
+    public void testConstructorSignBytesPositive7() {
+        byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+        int aSign = 1;
+        byte rBytes[] = {0, -12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+    
+    /**
+     * Create a negative number from a sign and an array of bytes.
+     * The number fits in an array of integers.
+     * The most significant byte is positive.
+     */
+    public void testConstructorSignBytesNegative1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+        int aSign = -1;
+        byte rBytes[] = {-13, -57, -101, 1, 75, -90, -46, -92, -4, 15};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+    
+    /**
+     * Create a negative number from a sign and an array of bytes.
+     * The number fits in an array of integers.
+     * The most significant byte is negative.
+     */
+    public void testConstructorSignBytesNegative2() {
+        byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+        int aSign = -1;
+        byte rBytes[] = {-1, 11, -57, -101, 1, 75, -90, -46, -92, -4, 15};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * Create a negative number from a sign and an array of bytes.
+     * The number fits in an integer.
+     */
+    public void testConstructorSignBytesNegative3() {
+        byte aBytes[] = {-12, 56, 100};
+        int aSign = -1;
+        byte rBytes[] = {-1, 11, -57, -100};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * Create a negative number from a sign and an array of bytes.
+     * The number of bytes is 4.
+     * The most significant byte is positive.
+     */
+    public void testConstructorSignBytesNegative4() {
+        byte aBytes[] = {127, 56, 100, -2};
+        int aSign = -1;
+        byte rBytes[] = {-128, -57, -101, 2};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * Create a negative number from a sign and an array of bytes.
+     * The number of bytes is 4.
+     * The most significant byte is negative.
+     */
+    public void testConstructorSignBytesNegative5() {
+        byte aBytes[] = {-127, 56, 100, -2};
+        int aSign = -1;
+        byte rBytes[] = {-1, 126, -57, -101, 2};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+    
+    /**
+     * Create a negative number from a sign and an array of bytes.
+     * The number of bytes is multiple of 4.
+     * The most significant byte is positive.
+     */
+    public void testConstructorSignBytesNegative6() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+        int aSign = -1;
+        byte rBytes[] = {-13, -57, -101, 1, 75, -90, -46, -92, -4, 14, -24, 101};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * Create a negative number from a sign and an array of bytes.
+     * The number of bytes is multiple of 4.
+     * The most significant byte is negative.
+     */
+    public void testConstructorSignBytesNegative7() {
+        byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+        int aSign = -1;
+        byte rBytes[] = {-1, 11, -57, -101, 1, 75, -90, -46, -92, -4, 14, -24, 101};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * Create a zero number from a sign and an array of zero bytes.
+     * The sign is -1.
+     */
+    public void testConstructorSignBytesZero1() {
+        byte aBytes[] = {-0, 0, +0, 0, 0, 00, 000};
+        int aSign = -1;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, aNumber.signum());
+    }
+
+    /**
+     * Create a zero number from a sign and an array of zero bytes.
+     * The sign is 0.
+     */
+    public void testConstructorSignBytesZero2() {
+        byte aBytes[] = {-0, 0, +0, 0, 0, 00, 000};
+        int aSign = 0;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, aNumber.signum());
+    }
+
+    /**
+     * Create a zero number from a sign and an array of zero bytes.
+     * The sign is 1.
+     */
+    public void testConstructorSignBytesZero3() {
+        byte aBytes[] = {-0, 0, +0, 0, 0, 00, 000};
+        int aSign = 1;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, aNumber.signum());
+    }
+
+    /**
+     * Create a zero number from a sign and an array of zero length.
+     * The sign is -1.
+     */
+    public void testConstructorSignBytesZeroNull1() {
+        byte aBytes[] = {};
+        int aSign = -1;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, aNumber.signum());
+    }
+
+    /**
+     * Create a zero number from a sign and an array of zero length.
+     * The sign is 0.
+     */
+    public void testConstructorSignBytesZeroNull2() {
+        byte aBytes[] = {};
+        int aSign = 0;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, aNumber.signum());
+    }
+
+    /**
+     * Create a zero number from a sign and an array of zero length.
+     * The sign is 1.
+     */
+    public void testConstructorSignBytesZeroNull3() {
+        byte aBytes[] = {};
+        int aSign = 1;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, aNumber.signum());
+    }
+
+    /**
+     * Create a number from a string value and radix.
+     * Verify an exception thrown if a radix is out of range
+     */
+    public void testConstructorStringException1() {
+        String value = "9234853876401";
+        int radix = 45;
+        try {
+            new BigInteger(value, radix);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+    
+    /**
+     * Create a number from a string value and radix.
+     * Verify an exception thrown if the string starts with a space.
+     */
+    public void testConstructorStringException2() {
+        String value = "   9234853876401";
+        int radix = 10;
+        try {
+            new BigInteger(value, radix);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+    
+    /**
+     * Create a number from a string value and radix.
+     * Verify an exception thrown if the string contains improper characters.
+     */
+    public void testConstructorStringException3() {
+        String value = "92348$*#78987";
+        int radix = 34;
+        try {
+            new BigInteger(value, radix);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+    
+    /**
+     * Create a number from a string value and radix.
+     * Verify an exception thrown if some digits are greater than radix.
+     */
+    public void testConstructorStringException4() {
+        String value = "98zv765hdsaiy";
+        int radix = 20;
+        try {
+            new BigInteger(value, radix);
+            fail("NumberFormatException has not been caught");
+        } catch (NumberFormatException e) {
+        }
+    }
+
+    /**
+     * Create a positive number from a string value and radix 2.
+     */
+    public void testConstructorStringRadix2() {
+        String value = "10101010101010101";
+        int radix = 2;
+        byte rBytes[] = {1, 85, 85};
+        BigInteger aNumber = new BigInteger(value, radix);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+    
+    /**
+     * Create a positive number from a string value and radix 8.
+     */
+    public void testConstructorStringRadix8() {
+        String value = "76356237071623450";
+        int radix = 8;
+        byte rBytes[] = {7, -50, -28, -8, -25, 39, 40};
+        BigInteger aNumber = new BigInteger(value, radix);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a positive number from a string value and radix 10.
+     */
+    public void testConstructorStringRadix10() {
+        String value = "987328901348934898";
+        int radix = 10;
+        byte rBytes[] = {13, -77, -78, 103, -103, 97, 68, -14};
+        BigInteger aNumber = new BigInteger(value, radix);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a positive number from a string value and radix 16.
+     */
+    public void testConstructorStringRadix16() {
+        String value = "fe2340a8b5ce790";
+        int radix = 16;
+        byte rBytes[] = {15, -30, 52, 10, -117, 92, -25, -112};
+        BigInteger aNumber = new BigInteger(value, radix);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a positive number from a string value and radix 36.
+     */
+    public void testConstructorStringRadix36() {
+        String value = "skdjgocvhdjfkl20jndjkf347ejg457";
+        int radix = 36;
+        byte rBytes[] = {0, -12, -116, 112, -105, 12, -36, 66, 108, 66, -20, -37, -15, 108, -7, 52, -99, -109, -8, -45, -5};
+        BigInteger aNumber = new BigInteger(value, radix);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * Create a negative number from a string value and radix 10.
+     */
+    public void testConstructorStringRadix10Negative() {
+        String value = "-234871376037";
+        int radix = 36;
+        byte rBytes[] = {-4, 48, 71, 62, -76, 93, -105, 13};
+        BigInteger aNumber = new BigInteger(value, radix);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * Create a zero number from a string value and radix 36.
+     */
+    public void testConstructorStringRadix10Zero() {
+        String value = "-00000000000000";
+        int radix = 10;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(value, radix);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, aNumber.signum());
+    }
+
+    /**
+     * Create a random number of 75 bits length.
+     */
+    public void testConstructorRandom() {
+        int bitLen = 75;
+        Random rnd = new Random();
+        BigInteger aNumber = new BigInteger(bitLen, rnd);
+        assertTrue("incorrect bitLength", aNumber.bitLength() <= bitLen);
+    }
+
+  public void testConstructorPrime() {
+    for (int rep = 0; rep < 2048; ++rep) {
+      Random rnd = new Random();
+      BigInteger b;
+      int bits;
+
+      // Create a 128-bit prime number.
+      bits = 128;
+      b = new BigInteger(bits, 10, rnd);
+      assertEquals(b.toString(), bits, b.bitLength());
+
+      // Create a prime number of 25 bits length.
+      bits = 25;
+      b = new BigInteger(bits, 10, rnd);
+      assertEquals(b.toString(), bits, b.bitLength());
+
+      // Create a prime number of 18 bits length.
+      bits = 18;
+      b = new BigInteger(bits, 10, rnd);
+      assertEquals(b.toString(), bits, b.bitLength());
+
+      // On Android, anything less than 16 bits used to be at least 16 bits
+      // because that's how OpenSSL behaves, but we recently fixed this...
+      bits = 2;
+      b = new BigInteger(bits, 10, rnd);
+      assertEquals(b.toString(), bits, b.bitLength());
+
+      // The 2-arg constructor has never used OpenSSL.
+      bits = 2;
+      b = new BigInteger(bits, rnd);
+      assertTrue(b.toString(), b.bitLength() <= bits);
+      assertTrue(b.toString(), b.intValue() <= 3);
+
+      bits = 16;
+      b = new BigInteger(bits, rnd);
+      assertTrue(b.toString(), b.bitLength() <= bits);
+    }
+  }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConvertTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConvertTest.java
new file mode 100644
index 0000000..d72923d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConvertTest.java
@@ -0,0 +1,792 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:   java.math.BigInteger
+ * Methods: intValue, longValue, toByteArray(), valueOf(long val),
+ * floatValue(), doubleValue()
+ */
+public class BigIntegerConvertTest extends TestCase {
+    /**
+     * Return the double value of ZERO. 
+     */
+    public void testDoubleValueZero() {
+        String a = "0";
+        double result = 0.0;
+        double aNumber = new BigInteger(a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive number to a double value. 
+     * The number's length is less than 64 bits.
+     */
+    public void testDoubleValuePositive1() {
+        String a = "27467238945";
+        double result = 2.7467238945E10;
+        double aNumber = new BigInteger(a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive number to a double value. 
+     * The number's bit length is inside [63, 1024].
+     */
+    public void testDoubleValuePositive2() {
+        String a = "2746723894572364578265426346273456972";
+        double result = 2.7467238945723645E36;
+        double aNumber = new BigInteger(a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a negative number to a double value. 
+     * The number's bit length is less than 64 bits.
+     */
+    public void testDoubleValueNegative1() {
+        String a = "-27467238945";
+        double result = -2.7467238945E10;
+        double aNumber = new BigInteger(a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a negative number to a double value. 
+     * The number's bit length is inside [63, 1024].
+     */
+    public void testDoubleValueNegative2() {
+        String a = "-2746723894572364578265426346273456972";
+        double result = -2.7467238945723645E36;
+        double aNumber = new BigInteger(a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive number to a double value. 
+     * Rounding is needed.
+     * The rounding bit is 1 and the next bit to the left is 1.
+     */
+    public void testDoubleValuePosRounded1() {
+        byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+        int aSign = 1;
+        double result = 1.54747264387948E26;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+    
+    /**
+     * Convert a positive number to a double value. 
+     * Rounding is needed.
+     * The rounding bit is 1 and the next bit to the left is 0
+     * but some of dropped bits are 1s.
+     */
+    public void testDoubleValuePosRounded2() {
+        byte[] a = {-128, 1, 2, 3, 4, 5, 36, 23, 1, -3, -5};
+        int aSign = 1;
+        double result = 1.547472643879479E26;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+        /**
+     * Convert a positive number to a double value. 
+     * Rounding is NOT needed.
+     */
+    public void testDoubleValuePosNotRounded() {
+        byte[] a = {-128, 1, 2, 3, 4, 5, -128, 23, 1, -3, -5};
+        int aSign = 1;
+        double result = 1.5474726438794828E26;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+    
+    /**
+     * Convert a positive number to a double value. 
+     * Rounding is needed.
+     */
+    public void testDoubleValueNegRounded1() {
+        byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+        int aSign = -1;
+        double result = -1.54747264387948E26;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+    
+    /**
+     * Convert a positive number to a double value. 
+     * Rounding is needed.
+     * The rounding bit is 1 and the next bit to the left is 0
+     * but some of dropped bits are 1s.
+     */
+    public void testDoubleValueNegRounded2() {
+        byte[] a = {-128, 1, 2, 3, 4, 5, 36, 23, 1, -3, -5};
+        int aSign = -1;
+        double result = -1.547472643879479E26;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive number to a double value. 
+     * Rounding is NOT needed.
+     */
+    public void testDoubleValueNegNotRounded() {
+        byte[] a = {-128, 1, 2, 3, 4, 5, -128, 23, 1, -3, -5};
+        int aSign = -1;
+        double result = -1.5474726438794828E26;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+    
+    /**
+     * Convert a positive number to a double value. 
+     * The exponent is 1023 and the mantissa is all 1s.
+     * The rounding bit is 0.
+     * The result is Double.MAX_VALUE.
+     */
+    public void testDoubleValuePosMaxValue() {
+        byte[] a = {0, -1, -1, -1, -1, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+           };
+        int aSign = 1;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == Double.MAX_VALUE);
+    }
+
+    /**
+     * Convert a negative number to a double value. 
+     * The exponent is 1023 and the mantissa is all 1s.
+     * The result is -Double.MAX_VALUE.
+     */
+    public void testDoubleValueNegMaxValue() {
+        byte[] a = {0, -1, -1, -1, -1, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+           };
+        int aSign = -1;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == -Double.MAX_VALUE);
+    }
+
+    /**
+     * Convert a positive number to a double value. 
+     * The exponent is 1023 and the mantissa is all 1s.
+     * The rounding bit is 1.
+     * The result is Double.POSITIVE_INFINITY.
+     */
+    public void testDoubleValuePositiveInfinity1() {
+        byte[] a = {-1, -1, -1, -1, -1, -1, -1, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
+           };
+        int aSign = 1;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == Double.POSITIVE_INFINITY);
+    }
+
+    /**
+     * Convert a positive number to a double value. 
+     * The number's bit length is greater than 1024.
+     */
+    public void testDoubleValuePositiveInfinity2() {
+        String a = "2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+        double aNumber = new BigInteger(a).doubleValue();
+        assertTrue(aNumber == Double.POSITIVE_INFINITY);
+    }
+
+    /**
+     * Convert a negative number to a double value. 
+     * The number's bit length is greater than 1024.
+     */
+    public void testDoubleValueNegativeInfinity1() {
+        String a = "-2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+        double aNumber = new BigInteger(a).doubleValue();
+        assertTrue(aNumber == Double.NEGATIVE_INFINITY);
+    }
+
+    /**
+     * Convert a negative number to a double value. 
+     * The exponent is 1023 and the mantissa is all 0s.
+     * The rounding bit is 0.
+     * The result is Double.NEGATIVE_INFINITY.
+     */
+    public void testDoubleValueNegativeInfinity2() {
+        byte[] a = {-1, -1, -1, -1, -1, -1, -1, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
+           };
+        int aSign = -1;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == Double.NEGATIVE_INFINITY);
+    }
+
+    /**
+     * Convert a positive number to a double value. 
+     * The exponent is 1023 and the mantissa is all 0s
+     * but the 54th bit (implicit) is 1.
+     */
+    public void testDoubleValuePosMantissaIsZero() {
+        byte[] a = {-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
+           };
+        int aSign = 1;
+        double result = 8.98846567431158E307;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive number to a double value. 
+     * The exponent is 1023 and the mantissa is all 0s
+     * but the 54th bit (implicit) is 1.
+     */
+    public void testDoubleValueNegMantissaIsZero() {
+        byte[] a = {-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
+           };
+        int aSign = -1;
+        double aNumber = new BigInteger(aSign, a).doubleValue();
+        assertTrue(aNumber == -8.98846567431158E307);
+    }
+
+    /**
+     * Return the float value of ZERO. 
+     */
+    public void testFloatValueZero() {
+        String a = "0";
+        float result = 0.0f;
+        float aNumber = new BigInteger(a).floatValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive number to a float value. 
+     * The number's length is less than 32 bits.
+     */
+    public void testFloatValuePositive1() {
+        String a = "27467238";
+        float result = 2.7467238E7f;
+        float aNumber = new BigInteger(a).floatValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive number to a float value. 
+     * The number's bit length is inside [32, 127].
+     */
+    public void testFloatValuePositive2() {
+        String a = "27467238945723645782";
+        float result = 2.7467239E19f;
+        float aNumber = new BigInteger(a).floatValue();
+        assertTrue(aNumber == result);
+    }
+    
+    /**
+     * Convert a negative number to a float value. 
+     * The number's bit length is less than 32 bits.
+     */
+    public void testFloatValueNegative1() {
+        String a = "-27467238";
+        float result = -2.7467238E7f;
+        float aNumber = new BigInteger(a).floatValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a negative number to a doufloatble value. 
+     * The number's bit length is inside [63, 1024].
+     */
+    public void testFloatValueNegative2() {
+        String a = "-27467238945723645782";
+        float result = -2.7467239E19f;
+        float aNumber = new BigInteger(a).floatValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive number to a float value. 
+     * Rounding is needed.
+     * The rounding bit is 1 and the next bit to the left is 1.
+     */
+    public void testFloatValuePosRounded1() {
+        byte[] a = {-128, 1, -1, -4, 4, 5, 60, 23, 1, -3, -5};
+        int aSign = 1;
+        float result = 1.5475195E26f;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == result);
+    }
+    
+    /**
+     * Convert a positive number to a float value. 
+     * Rounding is needed.
+     * The rounding bit is 1 and the next bit to the left is 0
+     * but some of dropped bits are 1s.
+     */
+    public void testFloatValuePosRounded2() {
+        byte[] a = {-128, 1, 2, -128, 4, 5, 60, 23, 1, -3, -5};
+        int aSign = 1;
+        float result = 1.5474728E26f;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == result);
+    }
+        /**
+     * Convert a positive number to a float value. 
+     * Rounding is NOT needed.
+     */
+    public void testFloatValuePosNotRounded() {
+        byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+        int aSign = 1;
+        float result = 1.5474726E26f;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == result);
+    }
+    
+    /**
+     * Convert a positive number to a float value. 
+     * Rounding is needed.
+     */
+    public void testFloatValueNegRounded1() {
+        byte[] a = {-128, 1, -1, -4, 4, 5, 60, 23, 1, -3, -5};
+        int aSign = -1;
+        float result = -1.5475195E26f;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == result);
+    }
+    
+    /**
+     * Convert a positive number to a float value. 
+     * Rounding is needed.
+     * The rounding bit is 1 and the next bit to the left is 0
+     * but some of dropped bits are 1s.
+     */
+    public void testFloatValueNegRounded2() {
+        byte[] a = {-128, 1, 2, -128, 4, 5, 60, 23, 1, -3, -5};
+        int aSign = -1;
+        float result = -1.5474728E26f;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive number to a float value. 
+     * Rounding is NOT needed.
+     */
+    public void testFloatValueNegNotRounded() {
+        byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+        int aSign = -1;
+        float result = -1.5474726E26f;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == result);
+    }
+    
+    /**
+     * Convert a positive number to a float value. 
+     * The exponent is 1023 and the mantissa is all 1s.
+     * The rounding bit is 0.
+     * The result is Float.MAX_VALUE.
+     */
+    public void testFloatValuePosMaxValue() {
+        byte[] a = {0, -1, -1, -1, 0, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+        int aSign = 1;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == Float.MAX_VALUE);
+    }
+
+    /**
+     * Convert a negative number to a float value. 
+     * The exponent is 1023 and the mantissa is all 1s.
+     * The rounding bit is 0.
+     * The result is -Float.MAX_VALUE.
+     */
+    public void testFloatValueNegMaxValue() {
+        byte[] a = {0, -1, -1, -1, 0, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+        int aSign = -1;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == -Float.MAX_VALUE);
+    }
+
+    /**
+     * Convert a positive number to a float value. 
+     * The exponent is 1023 and the mantissa is all 1s.
+     * The rounding bit is 1.
+     * The result is Float.POSITIVE_INFINITY.
+     */
+    public void testFloatValuePositiveInfinity1() {
+        byte[] a = {0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+        int aSign = 1;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == Float.POSITIVE_INFINITY);
+    }
+
+    /**
+     * Convert a positive number to a float value. 
+     * The number's bit length is greater than 127.
+     */
+    public void testFloatValuePositiveInfinity2() {
+        String a = "2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+        float aNumber = new BigInteger(a).floatValue();
+        assertTrue(aNumber == Float.POSITIVE_INFINITY);
+    }
+
+    /**
+     * Convert a negative number to a float value. 
+     * The number's bit length is greater than 127.
+     */
+    public void testFloatValueNegativeInfinity1() {
+        String a = "-2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+        float aNumber = new BigInteger(a).floatValue();
+        assertTrue(aNumber == Float.NEGATIVE_INFINITY);
+    }
+
+    /**
+     * Convert a negative number to a float value. 
+     * The exponent is 1023 and the mantissa is all 0s.
+     * The rounding bit is 0.
+     * The result is Float.NEGATIVE_INFINITY.
+     */
+    public void testFloatValueNegativeInfinity2() {
+        byte[] a = {0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+        int aSign = -1;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == Float.NEGATIVE_INFINITY);
+    }
+
+    /**
+     * Convert a positive number to a float value. 
+     * The exponent is 1023 and the mantissa is all 0s
+     * but the 54th bit (implicit) is 1.
+     */
+    public void testFloatValuePosMantissaIsZero() {
+        byte[] a = {-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+        int aSign = 1;
+        float result = 1.7014118E38f;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive number to a double value. 
+     * The exponent is 1023 and the mantissa is all 0s
+     * but the 54th bit (implicit) is 1.
+     */
+    public void testFloatValueNegMantissaIsZero() {
+        byte[] a = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+        int aSign = -1;
+        float aNumber = new BigInteger(aSign, a).floatValue();
+        assertTrue(aNumber == Float.NEGATIVE_INFINITY);
+    }
+
+    /**
+     * Convert a negative number to a float value. 
+     * The number's bit length is less than 32 bits.
+     */
+    public void testFloatValueBug2482() {
+        String a = "2147483649";
+        float result = 2.14748365E9f;
+        float aNumber = new BigInteger(a).floatValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a positive BigInteger to an integer value. 
+     * The low digit is positive
+     */
+    public void testIntValuePositive1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3};
+        int resInt = 1496144643;
+        int aNumber = new BigInteger(aBytes).intValue();
+        assertTrue(aNumber == resInt);
+    }
+
+    /**
+     * Convert a positive BigInteger to an integer value. 
+     * The low digit is positive
+     */
+    public void testIntValuePositive2() {
+        byte aBytes[] = {12, 56, 100};
+        int resInt = 800868;
+        int aNumber = new BigInteger(aBytes).intValue();
+        assertTrue(aNumber == resInt);
+    }
+
+    /**
+     * Convert a positive BigInteger to an integer value. 
+     * The low digit is negative.
+     */
+    public void testIntValuePositive3() {
+        byte aBytes[] = {56, 13, 78, -12, -5, 56, 100};
+        int sign = 1;
+        int resInt = -184862620;
+        int aNumber = new BigInteger(sign, aBytes).intValue();
+        assertTrue(aNumber == resInt);
+    }
+
+    /**
+     * Convert a negative BigInteger to an integer value.
+     * The low digit is negative.
+     */
+    public void testIntValueNegative1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, -128, 45, 91, 3};
+        int sign = -1;
+        int resInt = 2144511229;
+        int aNumber = new BigInteger(sign, aBytes).intValue();
+        assertTrue(aNumber == resInt);
+    }
+
+    /**
+     * Convert a negative BigInteger to an integer value.
+     * The low digit is negative.
+     */
+    public void testIntValueNegative2() {
+        byte aBytes[] = {-12, 56, 100};
+        int result = -771996;
+        int aNumber = new BigInteger(aBytes).intValue();
+        assertTrue(aNumber == result);
+    }
+    
+    /**
+     * Convert a negative BigInteger to an integer value. 
+     * The low digit is positive.
+     */
+    public void testIntValueNegative3() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 127, 45, 91, 3};
+        int sign = -1;
+        int resInt = -2133678851;
+        int aNumber = new BigInteger(sign, aBytes).intValue();
+        assertTrue(aNumber == resInt);
+    }
+
+    /**
+     * Convert a BigInteger to a positive long value
+     * The BigInteger is longer than int.
+     */
+    public void testLongValuePositive1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, 120, -34, -12, 45, 98};
+        long result = 3268209772258930018L;
+        long aNumber = new BigInteger(aBytes).longValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a number to a positive long value
+     * The number fits in a long.
+     */
+    public void testLongValuePositive2() {
+        byte aBytes[] = {12, 56, 100, 18, -105, 34, -18, 45};
+        long result = 880563758158769709L;
+        long aNumber = new BigInteger(aBytes).longValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a number to a negative long value
+     * The BigInteger is longer than int.
+     */
+    public void testLongValueNegative1() {
+        byte aBytes[] = {12, -1, 100, -2, -76, -128, 45, 91, 3};
+        long result = -43630045168837885L;
+        long aNumber = new BigInteger(aBytes).longValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * Convert a number to a negative long value
+     * The number fits in a long.
+     */
+    public void testLongValueNegative2() {
+        byte aBytes[] = {-12, 56, 100, 45, -101, 45, 98};
+        long result = -3315696807498398L;
+        long aNumber = new BigInteger(aBytes).longValue();
+        assertTrue(aNumber == result);
+    }
+
+    /**
+     * valueOf (long val): convert Integer.MAX_VALUE to a BigInteger.
+     */
+    public void testValueOfIntegerMax() {
+        long longVal = Integer.MAX_VALUE;
+        BigInteger aNumber = BigInteger.valueOf(longVal);
+        byte rBytes[] = {127, -1, -1, -1};
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * valueOf (long val): convert Integer.MIN_VALUE to a BigInteger.
+     */
+    public void testValueOfIntegerMin() {
+        long longVal = Integer.MIN_VALUE;
+        BigInteger aNumber = BigInteger.valueOf(longVal);
+        byte rBytes[] = {-128, 0, 0, 0};
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * valueOf (long val): convert Long.MAX_VALUE to a BigInteger.
+     */
+    public void testValueOfLongMax() {
+        long longVal = Long.MAX_VALUE;
+        BigInteger aNumber = BigInteger.valueOf(longVal);
+        byte rBytes[] = {127, -1, -1, -1, -1, -1, -1, -1};
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * valueOf (long val): convert Long.MIN_VALUE to a BigInteger.
+     */
+    public void testValueOfLongMin() {
+        long longVal = Long.MIN_VALUE;
+        BigInteger aNumber = BigInteger.valueOf(longVal);
+        byte rBytes[] = {-128, 0, 0, 0, 0, 0, 0, 0};
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * valueOf (long val): convert a positive long value to a BigInteger.
+     */
+    public void testValueOfLongPositive1() {
+        long longVal = 268209772258930018L;
+        BigInteger aNumber = BigInteger.valueOf(longVal);
+        byte rBytes[] = {3, -72, -33, 93, -24, -56, 45, 98};
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+
+    /**
+     * valueOf (long val): convert a positive long value to a BigInteger.
+     * The long value fits in integer.
+     */
+    public void testValueOfLongPositive2() {
+        long longVal = 58930018L;
+        BigInteger aNumber = BigInteger.valueOf(longVal);
+        byte rBytes[] = {3, -125, 51, 98};
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, aNumber.signum());
+    }
+    
+    /**
+     * valueOf (long val): convert a negative long value to a BigInteger.
+     */
+    public void testValueOfLongNegative1() {
+        long longVal = -268209772258930018L;
+        BigInteger aNumber = BigInteger.valueOf(longVal);
+        byte rBytes[] = {-4, 71, 32, -94, 23, 55, -46, -98};
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+
+    /**
+     * valueOf (long val): convert a negative long value to a BigInteger.
+     * The long value fits in integer.
+     */
+    public void testValueOfLongNegative2() {
+        long longVal = -58930018L;
+        BigInteger aNumber = BigInteger.valueOf(longVal);
+        byte rBytes[] = {-4, 124, -52, -98};
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, aNumber.signum());
+    }
+    /**
+     * valueOf (long val): convert a zero long value to a BigInteger.
+     */
+    public void testValueOfLongZero() {
+        long longVal = 0L;
+        BigInteger aNumber = BigInteger.valueOf(longVal);
+        byte rBytes[] = {0};
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = aNumber.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, aNumber.signum());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerDivideTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerDivideTest.java
new file mode 100644
index 0000000..3f2ab51
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerDivideTest.java
@@ -0,0 +1,666 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:   java.math.BigInteger
+ * Methods: divide, remainder, mod, and divideAndRemainder 
+ */
+public class BigIntegerDivideTest extends TestCase {
+    /**
+     * Divide by zero
+     */
+    public void testCase1() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {0};
+        int aSign = 1;
+        int bSign = 0;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        try {
+            aNumber.divide(bNumber);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+        }
+    }
+
+    /**
+     * Divide by ZERO
+     */
+    public void testCase2() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        int aSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ZERO;
+        try {
+            aNumber.divide(bNumber);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+        }
+    }
+
+    /**
+     * Divide two equal positive numbers
+     */
+    public void testCase3() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+        byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {1};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Divide two equal in absolute value numbers of different signs.
+     */
+    public void testCase4() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+        byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-1};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Divide two numbers of different length and different signs.
+     * The second is longer.
+     */
+    public void testCase5() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+        byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 1, 2, 3, 4, 5};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * Divide two positive numbers of the same length.
+     * The second is greater.
+     */
+    public void testCase6() {
+        byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127};
+        byte bBytes[] = {15, 100, 56, 7, 98, -1, 39, -128, 127};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * Divide two positive numbers.
+     */
+    public void testCase7() {
+        byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+        byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {23, 115, 11, 78, 35, -11};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Divide a positive number by a negative one.
+     */
+    public void testCase8() {
+        byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+        byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {-24, -116, -12, -79, -36, 11};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Divide a negative number by a positive one.
+     */
+    public void testCase9() {
+        byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+        byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-24, -116, -12, -79, -36, 11};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Divide two negative numbers.
+     */
+    public void testCase10() {
+        byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+        byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {23, 115, 11, 78, 35, -11};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Divide zero by a negative number.
+     */
+    public void testCase11() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+        int aSign = 0;
+        int bSign = -1;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+    
+    /**
+     * Divide ZERO by a negative number.
+     */
+    public void testCase12() {
+        byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+        int bSign = -1;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * Divide a positive number by ONE.
+     */
+    public void testCase13() {
+        byte aBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+        int aSign = 1;        
+        byte rBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ONE;
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Divide ONE by ONE.
+     */
+    public void testCase14() {
+        byte rBytes[] = {1};
+        BigInteger aNumber = BigInteger.ONE;
+        BigInteger bNumber = BigInteger.ONE;
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * Verifies the case when borrow != 0 in the private divide method.
+     */
+    public void testDivisionKnuth1() {
+        byte aBytes[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {-3, -3, -3, -3};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -5, -12, -33, -96, -36, -105, -56, 92, 15, 48, -109};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Verifies the case when the divisor is already normalized.
+     */
+    public void testDivisionKnuthIsNormalized() {
+        byte aBytes[] = {-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
+        byte bBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {0, -9, -8, -7, -6, -5, -4, -3};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Verifies the case when the first digits of the dividend
+     * and divisor equal.
+     */
+    public void testDivisionKnuthFirstDigitsEqual() {
+        byte aBytes[] = {2, -3, -4, -5, -1, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
+        byte bBytes[] = {2, -3, -4, -5, -1, -1, -1, -1};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {0, -1, -1, -1, -1, -2, -88, -60, 41};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Divide the number of one digit by the number of one digit 
+     */
+    public void testDivisionKnuthOneDigitByOneDigit() {
+        byte aBytes[] = {113, -83, 123, -5};
+        byte bBytes[] = {2, -3, -4, -5};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {-37};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Divide the number of multi digits by the number of one digit 
+     */
+    public void testDivisionKnuthMultiDigitsByOneDigit() {
+        byte aBytes[] = {113, -83, 123, -5, 18, -34, 67, 39, -29};
+        byte bBytes[] = {2, -3, -4, -5};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {-38, 2, 7, 30, 109, -43};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.divide(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Remainder of division by zero
+     */
+    public void testCase15() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {0};
+        int aSign = 1;
+        int bSign = 0;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        try {
+            aNumber.remainder(bNumber);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+        }
+    }
+
+    /**
+     * Remainder of division of equal numbers
+     */
+    public void testCase16() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+        byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.remainder(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * Remainder of division of two positive numbers
+     */
+    public void testCase17() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+        byte bBytes[] = {27, -15, 65, 39, 100};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {12, -21, 73, 56, 27};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.remainder(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Remainder of division of two negative numbers
+     */
+    public void testCase18() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+        byte bBytes[] = {27, -15, 65, 39, 100};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-13, 20, -74, -57, -27};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.remainder(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Remainder of division of two numbers of different signs.
+     * The first is positive.
+     */
+    public void testCase19() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+        byte bBytes[] = {27, -15, 65, 39, 100};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {12, -21, 73, 56, 27};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.remainder(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * Remainder of division of two numbers of different signs.
+     * The first is negative.
+     */
+    public void testCase20() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+        byte bBytes[] = {27, -15, 65, 39, 100};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-13, 20, -74, -57, -27};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.remainder(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Tests the step D6 from the Knuth algorithm
+     */
+    public void testRemainderKnuth1() {
+        byte aBytes[] = {-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1};
+        byte bBytes[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {1, 2, 3, 4, 5, 6, 7, 7, 18, -89};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.remainder(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Divide the number of one digit by the number of one digit 
+     */
+    public void testRemainderKnuthOneDigitByOneDigit() {
+        byte aBytes[] = {113, -83, 123, -5};
+        byte bBytes[] = {2, -3, -4, -50};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {2, -9, -14, 53};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.remainder(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Divide the number of multi digits by the number of one digit 
+     */
+    public void testRemainderKnuthMultiDigitsByOneDigit() {
+        byte aBytes[] = {113, -83, 123, -5, 18, -34, 67, 39, -29};
+        byte bBytes[] = {2, -3, -4, -50};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {2, -37, -60, 59};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.remainder(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * divideAndRemainder of two numbers of different signs.
+     * The first is negative.
+     */
+    public void testCase21() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+        byte bBytes[] = {27, -15, 65, 39, 100};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[][] = {
+                {-5, 94, -115, -74, -85, 84},
+                {-13, 20, -74, -57, -27}
+        };
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result[] = aNumber.divideAndRemainder(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result[0].toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            if (resBytes[i] != rBytes[0][i]) {
+                fail("Incorrect quotation");
+            }
+        }
+        assertEquals(-1, result[0].signum());
+        resBytes = result[1].toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            if (resBytes[i] != rBytes[1][i]) {
+                fail("Incorrect remainder");
+            }
+            assertEquals(-1, result[1].signum());
+        }
+    }
+    
+    /**
+     * mod when modulus is negative
+     */
+    public void testCase22() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {1, 30, 40, 56, -1, 45};
+        int aSign = 1;
+        int bSign = -1;        
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        try {
+            aNumber.mod(bNumber);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+        }
+    }
+
+    /**
+     * mod when a divisor is positive
+     */
+    public void testCase23() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+        byte bBytes[] = {27, -15, 65, 39, 100};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {12, -21, 73, 56, 27};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.mod(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * mod when a divisor is negative
+     */
+    public void testCase24() {
+        byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+        byte bBytes[] = {27, -15, 65, 39, 100};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {15, 5, -9, -17, 73};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.mod(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerHashCodeTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerHashCodeTest.java
new file mode 100644
index 0000000..52bf56f
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerHashCodeTest.java
@@ -0,0 +1,80 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+
+/**
+ * Class:   java.math.BigInteger
+ * Method: hashCode()
+ */
+public class BigIntegerHashCodeTest extends TestCase {
+    /**
+     * Test hash codes for the same object
+     */
+    public void testSameObject() {
+        String value1 = "12378246728727834290276457386374882976782849";
+        String value2 = "-5634562095872038262928728727834290276457386374882976782849";
+        BigInteger aNumber1 = new BigInteger(value1);
+        BigInteger aNumber2 = new BigInteger(value2);
+        int code1 = aNumber1.hashCode();
+        aNumber1.add(aNumber2).shiftLeft(125);
+        aNumber1.subtract(aNumber2).shiftRight(125);
+        aNumber1.multiply(aNumber2).toByteArray();
+        aNumber1.divide(aNumber2).bitLength();
+        aNumber1.gcd(aNumber2).pow(7);
+        int code2 = aNumber1.hashCode();
+        assertTrue("hash codes for the same object differ", code1 == code2);
+    }
+
+    /**
+     * Test hash codes for equal objects.
+     */
+    public void testEqualObjects() {
+        String value1 = "12378246728727834290276457386374882976782849";
+        String value2 = "12378246728727834290276457386374882976782849";
+        BigInteger aNumber1 = new BigInteger(value1);
+        BigInteger aNumber2 = new BigInteger(value2);
+        int code1 = aNumber1.hashCode();
+        int code2 = aNumber2.hashCode();
+        if (aNumber1.equals(aNumber2)) {
+            assertTrue("hash codes for equal objects are unequal", code1 == code2);
+        }
+    }
+
+    /**
+     * Test hash codes for unequal objects.
+     * The codes are unequal.
+     */
+    public void testUnequalObjectsUnequal() {
+        String value1 = "12378246728727834290276457386374882976782849";
+        String value2 = "-5634562095872038262928728727834290276457386374882976782849";
+        BigInteger aNumber1 = new BigInteger(value1);
+        BigInteger aNumber2 = new BigInteger(value2);
+        int code1 = aNumber1.hashCode();
+        int code2 = aNumber2.hashCode();
+        if (!aNumber1.equals(aNumber2)) {
+            assertTrue("hash codes for unequal objects are equal", code1 != code2);
+        }
+    }      
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerModPowTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerModPowTest.java
new file mode 100644
index 0000000..4af4d9d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerModPowTest.java
@@ -0,0 +1,351 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:   java.math.BigInteger
+ * Methods: modPow, modInverse, and gcd 
+ */
+public class BigIntegerModPowTest extends TestCase {
+	/**
+	 * modPow: non-positive modulus
+	 */
+	public void testModPowException() {
+		byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+		byte eBytes[] = {1, 2, 3, 4, 5};
+		byte mBytes[] = {1, 2, 3};
+		int aSign = 1;
+		int eSign = 1;		
+		int mSign = -1;		
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger exp = new BigInteger(eSign, eBytes);
+		BigInteger modulus = new BigInteger(mSign, mBytes);
+		try {
+			aNumber.modPow(exp, modulus);
+			fail("ArithmeticException has not been caught");
+		} catch (ArithmeticException e) {
+		}
+
+        try {
+            BigInteger.ZERO.modPow(new BigInteger("-1"), new BigInteger("10"));
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+            // expected
+        }
+	}
+
+	/**
+	 * modPow: positive exponent
+	 */
+	public void testModPowPosExp() {
+		byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75, 48, -7};
+		byte eBytes[] = {27, -15, 65, 39};
+		byte mBytes[] = {-128, 2, 3, 4, 5};
+		int aSign = 1;
+		int eSign = 1;		
+		int mSign = 1;		
+		byte rBytes[] = {113, 100, -84, -28, -85};
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger exp = 	 new BigInteger(eSign, eBytes);
+		BigInteger modulus = new BigInteger(mSign, mBytes);
+		BigInteger result = aNumber.modPow(exp, modulus);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+	
+	/**
+	 * modPow: negative exponent
+	 */
+	public void testModPowNegExp() {
+		byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75, 48, -7};
+		byte eBytes[] = {27, -15, 65, 39};
+		byte mBytes[] = {-128, 2, 3, 4, 5};
+		int aSign = 1;
+		int eSign = -1;		
+		int mSign = 1;		
+		byte rBytes[] = {12, 118, 46, 86, 92};
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger exp = 	 new BigInteger(eSign, eBytes);
+		BigInteger modulus = new BigInteger(mSign, mBytes);
+		BigInteger result = aNumber.modPow(exp, modulus);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+
+    public void testModPowZeroExp() {
+        BigInteger exp = new BigInteger("0");
+        BigInteger[] base = new BigInteger[] {new BigInteger("-1"), new BigInteger("0"), new BigInteger("1")};
+        BigInteger[] mod = new BigInteger[] {new BigInteger("2"), new BigInteger("10"), new BigInteger("2147483648")};
+
+        for (int i = 0; i < base.length; ++i) {
+            for (int j = 0; j < mod.length; ++j) {
+                assertEquals(base[i] + " modePow(" + exp + ", " + mod[j]
+                        + ") should be " + BigInteger.ONE, BigInteger.ONE,
+                        base[i].modPow(exp, mod[j]));
+            }
+        }
+
+        mod = new BigInteger[] {new BigInteger("1")};
+        for (int i = 0; i < base.length; ++i) {
+            for (int j = 0; j < mod.length; ++j) {
+                assertEquals(base[i] + " modePow(" + exp + ", " + mod[j]
+                        + ") should be " + BigInteger.ZERO, BigInteger.ZERO,
+                        base[i].modPow(exp, mod[j]));
+            }
+        }
+    }
+
+	/**
+	 * modInverse: non-positive modulus
+	 */
+	public void testmodInverseException() {
+		byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+		byte mBytes[] = {1, 2, 3};
+		int aSign = 1;
+		int mSign = -1;		
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger modulus = new BigInteger(mSign, mBytes);
+		try {
+			aNumber.modInverse(modulus);
+			fail("ArithmeticException has not been caught");
+		} catch (ArithmeticException e) {
+		}
+	}
+	
+	/**
+	 * modInverse: non-invertible number
+	 */
+	public void testmodInverseNonInvertible() {
+		byte aBytes[] = {-15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+		byte mBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
+		int aSign = 1;
+		int mSign = 1;		
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger modulus = new BigInteger(mSign, mBytes);
+		try {
+			aNumber.modInverse(modulus);
+			fail("ArithmeticException has not been caught");
+		} catch (ArithmeticException e) {
+		}
+	}
+
+	/**
+	 * modInverse: positive number
+	 */
+	public void testmodInversePos1() {
+		byte aBytes[] = {24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+		byte mBytes[] = {122, 45, 36, 100, 122, 45};
+		int aSign = 1;
+		int mSign = 1;		
+		byte rBytes[] = {47, 3, 96, 62, 87, 19};
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger modulus = new BigInteger(mSign, mBytes);
+		BigInteger result = aNumber.modInverse(modulus);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+
+	/**
+	 * modInverse: positive number (another case: a < 0)
+	 */
+	public void testmodInversePos2() {
+		byte aBytes[] = {15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+		byte mBytes[] = {2, 122, 45, 36, 100};
+		int aSign = 1;
+		int mSign = 1;		
+		byte rBytes[] = {1, -93, 40, 127, 73};
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger modulus = new BigInteger(mSign, mBytes);
+		BigInteger result = aNumber.modInverse(modulus);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+
+	/**
+	 * modInverse: negative number
+	 */
+	public void testmodInverseNeg1() {
+		byte aBytes[] = {15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+		byte mBytes[] = {2, 122, 45, 36, 100};
+		int aSign = -1;
+		int mSign = 1;		
+		byte rBytes[] = {0, -41, 4, -91, 27};
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger modulus = new BigInteger(mSign, mBytes);
+		BigInteger result = aNumber.modInverse(modulus);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+
+	/**
+	 * modInverse: negative number (another case: x < 0)
+	 */
+	public void testmodInverseNeg2() {
+		byte aBytes[] = {-15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+		byte mBytes[] = {122, 2, 4, 122, 2, 4};
+		byte rBytes[] = {85, 47, 127, 4, -128, 45};
+		BigInteger aNumber = new BigInteger(aBytes);
+		BigInteger modulus = new BigInteger(mBytes);
+		BigInteger result = aNumber.modInverse(modulus);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+	
+	/**
+	 * gcd: the second number is zero
+	 */
+	public void testGcdSecondZero() {
+		byte aBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+		byte bBytes[] = {0};
+		int aSign = 1;
+		int bSign = 1;
+		byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger bNumber = new BigInteger(bSign, bBytes);
+		BigInteger result = aNumber.gcd(bNumber);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+
+	/**
+	 * gcd: the first number is zero
+	 */
+	public void testGcdFirstZero() {
+		byte aBytes[] = {0};
+		byte bBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+		int aSign = 1;
+		int bSign = 1;
+		byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger bNumber = new BigInteger(bSign, bBytes);
+		BigInteger result = aNumber.gcd(bNumber);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+	
+	/**
+	 * gcd: the first number is ZERO
+	 */
+	public void testGcdFirstZERO() {
+		byte bBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+		int bSign = 1;
+		byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+		BigInteger aNumber = BigInteger.ZERO;
+		BigInteger bNumber = new BigInteger(bSign, bBytes);
+		BigInteger result = aNumber.gcd(bNumber);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+
+	/**
+	 * gcd: both numbers are zeros
+	 */
+	public void testGcdBothZeros() {
+		byte rBytes[] = {0};
+		BigInteger aNumber = new BigInteger("0");
+		BigInteger bNumber = BigInteger.valueOf(0L);
+		BigInteger result = aNumber.gcd(bNumber);
+		byte resBytes[] = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 0, result.signum());
+	}
+
+	/**
+	 * gcd: the first number is longer
+	 */
+	public void testGcdFirstLonger() {
+		byte aBytes[] = {-15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+		byte bBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
+		int aSign = 1;
+		int bSign = 1;
+		byte rBytes[] = {7};
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger bNumber = new BigInteger(bSign, bBytes);
+		BigInteger result = aNumber.gcd(bNumber);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+
+	/**
+	 * gcd: the second number is longer
+	 */
+	public void testGcdSecondLonger() {
+		byte aBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
+		byte bBytes[] = {-15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+		int aSign = 1;
+		int bSign = 1;
+		byte rBytes[] = {7};
+		BigInteger aNumber = new BigInteger(aSign, aBytes);
+		BigInteger bNumber = new BigInteger(bSign, bBytes);
+		BigInteger result = aNumber.gcd(bNumber);
+		byte resBytes[] = new byte[rBytes.length];
+		resBytes = result.toByteArray();
+		for(int i = 0; i < resBytes.length; i++) {
+			assertTrue(resBytes[i] == rBytes[i]);
+		}
+		assertEquals("incorrect sign", 1, result.signum());
+	}
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerMultiplyTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerMultiplyTest.java
new file mode 100644
index 0000000..0bfcbf0
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerMultiplyTest.java
@@ -0,0 +1,388 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:  java.math.BigInteger
+ * Method: multiply 
+ */
+public class BigIntegerMultiplyTest extends TestCase {
+    /**
+     * Multiply two negative numbers of the same length
+     */
+    public void testCase1() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {10, 40, 100, -55, 96, 51, 76, 40, -45, 85, 105, 4, 28, -86, -117, -52, 100, 120, 90};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Multiply two numbers of the same length and different signs.
+     * The first is negative.
+     */
+    public void testCase2() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-11, -41, -101, 54, -97, -52, -77, -41, 44, -86, -106, -5, -29, 85, 116, 51, -101, -121, -90};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Multiply two positive numbers of different length.
+     * The first is longer.
+     */
+    public void testCase3() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {10, 40, 100, -55, 96, 51, 76, 40, -45, 85, 115, 44, -127, 
+                         115, -21, -62, -15, 85, 64, -87, -2, -36, -36, -106};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Multiply two positive numbers of different length.
+     * The second is longer.
+     */
+    public void testCase4() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {10, 40, 100, -55, 96, 51, 76, 40, -45, 85, 115, 44, -127, 
+                         115, -21, -62, -15, 85, 64, -87, -2, -36, -36, -106};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Multiply two numbers of different length and different signs.
+     * The first is positive.
+     * The first is longer.
+     */
+    public void testCase5() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {-11, -41, -101, 54, -97, -52, -77, -41, 44, -86, -116, -45, 126,
+                         -116, 20, 61, 14, -86, -65, 86, 1, 35, 35, 106};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Multiply two numbers of different length and different signs.
+     * The first is positive.
+     * The second is longer.
+     */
+    public void testCase6() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {-11, -41, -101, 54, -97, -52, -77, -41, 44, -86, -116, -45, 126,
+                         -116, 20, 61, 14, -86, -65, 86, 1, 35, 35, 106};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Multiply a number by zero.
+     */
+    public void testCase7() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+        byte bBytes[] = {0};
+        int aSign = 1;
+        int bSign = 0;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * Multiply a number by ZERO.
+     */
+    public void testCase8() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+        int aSign = 1;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ZERO;
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * Multiply a positive number by ONE.
+     */
+    public void testCase9() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+        int aSign = 1;
+        byte rBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ONE;
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Multiply a negative number by ONE.
+     */
+    public void testCase10() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+        int aSign = -1;
+        byte rBytes[] = {-2, -3, -4, -5, -6, -7, -8, -2, -3, -4, -2, -3, -4, -5, -5};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ONE;
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+    
+    /**
+     * Multiply two numbers of 4 bytes length.
+     */
+    public void testIntbyInt1() {
+        byte aBytes[] = {10, 20, 30, 40};
+        byte bBytes[] = {1, 2, 3, 4};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {-11, -41, -101, 55, 5, 15, 96};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+    
+    /**
+     * Multiply two numbers of 4 bytes length.
+     */
+    public void testIntbyInt2() {
+        byte aBytes[] = {-1, -1, -1, -1};
+        byte bBytes[] = {-1, -1, -1, -1};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -1, -1, -1, -2, 0, 0, 0, 1};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.multiply(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * Negative exponent.
+     */
+    public void testPowException() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+        int aSign = 1;
+        int exp = -5;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        try {
+            aNumber.pow(exp);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+        }
+    }
+
+    /**
+     * Exponentiation of a negative number to an odd exponent.
+     */
+    public void testPowNegativeNumToOddExp() {
+        byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+        int aSign = -1;
+        int exp = 5;
+        byte rBytes[] = {-21, -94, -42, -15, -127, 113, -50, -88, 115, -35, 3,
+            59, -92, 111, -75, 103, -42, 41, 34, -114, 99, -32, 105, -59, 127,
+            45, 108, 74, -93, 105, 33, 12, -5, -20, 17, -21, -119, -127, -115,
+            27, -122, 26, -67, 109, -125, 16, 91, -70, 109};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.pow(exp);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Exponentiation of a negative number to an even exponent.
+     */
+    public void testPowNegativeNumToEvenExp() {
+        byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+        int aSign = -1;
+        int exp = 4;
+        byte rBytes[] = {102, 107, -122, -43, -52, -20, -27, 25, -9, 88, -13,
+            75, 78, 81, -33, -77, 39, 27, -37, 106, 121, -73, 108, -47, -101,
+            80, -25, 71, 13, 94, -7, -33, 1, -17, -65, -70, -61, -3, -47};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.pow(exp);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Exponentiation of a negative number to zero exponent.
+     */
+    public void testPowNegativeNumToZeroExp() {
+        byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+        int aSign = -1;
+        int exp = 0;
+        byte rBytes[] = {1};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.pow(exp);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Exponentiation of a positive number.
+     */
+    public void testPowPositiveNum() {
+        byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+        int aSign = 1;
+        int exp = 5;
+        byte rBytes[] = {20, 93, 41, 14, 126, -114, 49, 87, -116, 34, -4, -60,
+            91, -112, 74, -104, 41, -42, -35, 113, -100, 31, -106, 58, -128,
+            -46, -109, -75, 92, -106, -34, -13, 4, 19, -18, 20, 118, 126, 114,
+            -28, 121, -27, 66, -110, 124, -17, -92, 69, -109};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.pow(exp);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Exponentiation of a negative number to zero exponent.
+     */
+    public void testPowPositiveNumToZeroExp() {
+        byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+        int aSign = 1;
+        int exp = 0;
+        byte rBytes[] = {1};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.pow(exp);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerNotTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerNotTest.java
new file mode 100644
index 0000000..615afc1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerNotTest.java
@@ -0,0 +1,192 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:  java.math.BigInteger
+ * Methods: and, andNot
+ */
+public class BigIntegerNotTest extends TestCase {
+    /**
+     * andNot for two positive numbers; the first is longer
+     */
+    public void testAndNotPosPosFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -128, 9, 56, 100, 0, 0, 1, 1, 90, 1, -32, 0, 10, -126, 21, 82, -31, -96};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.andNot(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * andNot for two positive numbers; the first is shorter
+     */
+    public void testAndNotPosPosFirstShorter() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 2};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.andNot(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * andNot for two negative numbers; the first is longer
+     */
+    public void testAndNotNegNegFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 2};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.andNot(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * andNot for a negative and a positive numbers; the first is longer
+     */
+    public void testNegPosFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-1, 127, -10, -57, -101, 1, 2, 2, 2, -96, -16, 8, -40, -59, 68, -88, -88, 16, 72};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.andNot(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Not for ZERO 
+     */
+    public void testNotZero() {
+        byte rBytes[] = {-1};
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger result = aNumber.not();
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Not for ONE
+     */
+    public void testNotOne() {
+        byte rBytes[] = {-2};
+        BigInteger aNumber = BigInteger.ONE;
+        BigInteger result = aNumber.not();
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Not for a positive number
+     */
+    public void testNotPos() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+        int aSign = 1;
+        byte rBytes[] = {-1, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -27, 116};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.not();
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Not for a negative number
+     */
+    public void testNotNeg() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+        int aSign = -1;
+        byte rBytes[] = {0, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -118};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.not();
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Not for a negative number
+     */
+
+    public void testNotSpecialCase() {
+        byte aBytes[] = {-1, -1, -1, -1};
+        int aSign = 1;
+        byte rBytes[] = {-1, 0, 0, 0, 0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.not();
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+}
\ No newline at end of file
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java
new file mode 100644
index 0000000..9b7c198
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java
@@ -0,0 +1,1375 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:   java.math.BigInteger
+ * Methods: bitLength, shiftLeft, shiftRight,
+ * clearBit, flipBit, setBit, testBit
+ */
+public class BigIntegerOperateBitsTest extends TestCase {
+    /**
+     * bitCount() of zero.
+     */
+    public void testBitCountZero() {
+        BigInteger aNumber = new BigInteger("0");
+        assertEquals(0, aNumber.bitCount());
+    }
+
+    /**
+     * bitCount() of a negative number.
+     */
+    public void testBitCountNeg() {
+        BigInteger aNumber = new BigInteger("-12378634756382937873487638746283767238657872368748726875");
+        assertEquals(87, aNumber.bitCount());
+    }
+
+    /**
+     * bitCount() of a negative number.
+     */
+    public void testBitCountPos() {
+        BigInteger aNumber = new BigInteger("12378634756343564757582937873487638746283767238657872368748726875");
+        assertEquals(107, aNumber.bitCount());
+    }
+
+    /**
+     * bitLength() of zero.
+     */
+    public void testBitLengthZero() {
+        BigInteger aNumber = new BigInteger("0");
+        assertEquals(0, aNumber.bitLength());
+    }
+
+    /**
+     * bitLength() of a positive number.
+     */
+    public void testBitLengthPositive1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertEquals(108, aNumber.bitLength());
+    }
+
+    /**
+     * bitLength() of a positive number with the leftmost bit set
+     */
+    public void testBitLengthPositive2() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertEquals(96, aNumber.bitLength());
+    }
+
+    /**
+     * bitLength() of a positive number which is a power of 2
+     */
+    public void testBitLengthPositive3() {
+        byte aBytes[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+        int aSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertEquals(81, aNumber.bitLength());
+    }
+
+    /**
+     * bitLength() of a negative number.
+     */
+    public void testBitLengthNegative1() {
+        byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+        int aSign = -1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertEquals(108, aNumber.bitLength());
+    }
+
+    /**
+     * bitLength() of a negative number with the leftmost bit set
+     */
+    public void testBitLengthNegative2() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertEquals(96, aNumber.bitLength());
+    }
+    
+    /**
+     * bitLength() of a negative number which is a power of 2
+     */
+    public void testBitLengthNegative3() {
+        byte aBytes[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+        int aSign = -1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertEquals(80, aNumber.bitLength());
+    }
+
+    /**
+     * clearBit(int n) of a negative n
+     */
+    public void testClearBitException() {
+        byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = -7;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        try {
+            aNumber.clearBit(number);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+        }
+    }
+
+    /**
+     * clearBit(int n) outside zero
+     */
+    public void testClearBitZero() {
+        byte aBytes[] = {0};
+        int aSign = 0;
+        int number = 0;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * clearBit(int n) outside zero
+     */
+    public void testClearBitZeroOutside1() {
+        byte aBytes[] = {0};
+        int aSign = 0;
+        int number = 95;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * clearBit(int n) inside a negative number
+     */
+    public void testClearBitNegativeInside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 15;
+        byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, 92, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * clearBit(int n) inside a negative number
+     */
+    public void testClearBitNegativeInside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 44;
+        byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -62, -92, -4, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * clearBit(2) in the negative number with all ones in bit representation
+     */
+    public void testClearBitNegativeInside3() {
+        String as = "-18446744073709551615";
+        int number = 2;
+        BigInteger aNumber = new BigInteger(as);
+        BigInteger result = aNumber.clearBit(number);
+        assertEquals(as, result.toString());
+    }
+
+    /**
+     * clearBit(0) in the negative number of length 1
+     * with all ones in bit representation.
+     * the resulting number's length is 2.
+     */
+    public void testClearBitNegativeInside4() {
+        String as = "-4294967295";
+        String res = "-4294967296";
+        int number = 0;
+        BigInteger aNumber = new BigInteger(as);
+        BigInteger result = aNumber.clearBit(number);
+        assertEquals(res, result.toString());
+    }
+
+    /**
+     * clearBit(0) in the negative number of length 2
+     * with all ones in bit representation.
+     * the resulting number's length is 3.
+     */
+    public void testClearBitNegativeInside5() {
+        String as = "-18446744073709551615";
+        String res = "-18446744073709551616";
+        int number = 0;
+        BigInteger aNumber = new BigInteger(as);
+        BigInteger result = aNumber.clearBit(number);
+        assertEquals(res, result.toString());
+    }
+
+    /**
+     * clearBit(int n) outside a negative number
+     */
+    public void testClearBitNegativeOutside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 150;
+        byte rBytes[] = {-65, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * clearBit(int n) outside a negative number
+     */
+    public void testClearBitNegativeOutside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 165;
+        byte rBytes[] = {-33, -1, -1, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * clearBit(int n) inside a positive number
+     */
+    public void testClearBitPositiveInside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 20;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -31, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * clearBit(int n) inside a positive number
+     */
+    public void testClearBitPositiveInside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 17;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * clearBit(int n) inside a positive number
+     */
+    public void testClearBitPositiveInside3() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 45;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 13, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * clearBit(int n) inside a positive number
+     */
+    public void testClearBitPositiveInside4 () {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 50;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * clearBit(int n) inside a positive number
+     */
+    public void testClearBitPositiveInside5 () {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 63;
+        byte rBytes[] = {1, -128, 56, 100, -2, 52, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * clearBit(int n) outside a positive number
+     */
+    public void testClearBitPositiveOutside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 150;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * clearBit(int n) outside a positive number
+     */
+    public void testClearBitPositiveOutside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 191;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * clearBit(int n) the leftmost bit in a negative number
+     */
+    public void testClearBitTopNegative() {
+        byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+        int aSign = -1;
+        int number = 63;
+        byte rBytes[] = {-1, 127, -2, 127, -57, -101, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.clearBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * flipBit(int n) of a negative n
+     */
+    public void testFlipBitException() {
+        byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = -7;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        try {
+            aNumber.flipBit(number);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+        }
+    }
+
+    /**
+     * flipBit(int n) zero
+     */
+    public void testFlipBitZero() {
+        byte aBytes[] = {0};
+        int aSign = 0;
+        int number = 0;
+        byte rBytes[] = {1};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * flipBit(int n) outside zero
+     */
+    public void testFlipBitZeroOutside1() {
+        byte aBytes[] = {0};
+        int aSign = 0;
+        int number = 62;
+        byte rBytes[] = {64, 0, 0, 0, 0, 0, 0, 0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue("incorrect value", resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * flipBit(int n) outside zero
+     */
+    public void testFlipBitZeroOutside2() {
+        byte aBytes[] = {0};
+        int aSign = 0;
+        int number = 63;
+        byte rBytes[] = {0, -128, 0, 0, 0, 0, 0, 0, 0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue("incorrect value", resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * flipBit(int n) the leftmost bit in a negative number
+     */
+    public void testFlipBitLeftmostNegative() {
+        byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+        int aSign = -1;
+        int number = 48;
+        byte rBytes[] = {-1, 127, -57, -101, 14, -36, -26, 49};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+    
+    /**
+     * flipBit(int n) the leftmost bit in a positive number
+     */
+    public void testFlipBitLeftmostPositive() {
+        byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+        int aSign = 1;
+        int number = 48;
+        byte rBytes[] = {0, -128, 56, 100, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * flipBit(int n) inside a negative number
+     */
+    public void testFlipBitNegativeInside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 15;
+        byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, 92, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * flipBit(int n) inside a negative number
+     */
+    public void testFlipBitNegativeInside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 45;
+        byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -14, -92, -4, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * flipBit(int n) inside a negative number with all ones in bit representation 
+     */
+    public void testFlipBitNegativeInside3() {
+        String as = "-18446744073709551615";
+        String res = "-18446744073709551611";
+        int number = 2;
+        BigInteger aNumber = new BigInteger(as);
+        BigInteger result = aNumber.flipBit(number);
+        assertEquals(res, result.toString());
+    }
+
+    /**
+     * flipBit(0) in the negative number of length 1
+     * with all ones in bit representation.
+     * the resulting number's length is 2.
+     */
+    public void testFlipBitNegativeInside4() {
+        String as = "-4294967295";
+        String res = "-4294967296";
+        int number = 0;
+        BigInteger aNumber = new BigInteger(as);
+        BigInteger result = aNumber.flipBit(number);
+        assertEquals(res, result.toString());
+    }
+
+    /**
+     * flipBit(0) in the negative number of length 2
+     * with all ones in bit representation.
+     * the resulting number's length is 3.
+     */
+    public void testFlipBitNegativeInside5() {
+        String as = "-18446744073709551615";
+        String res = "-18446744073709551616";
+        int number = 0;
+        BigInteger aNumber = new BigInteger(as);
+        BigInteger result = aNumber.flipBit(number);
+        assertEquals(res, result.toString());
+    }
+
+    /**
+     * flipBit(int n) outside a negative number
+     */
+    public void testFlipBitNegativeOutside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 150;
+        byte rBytes[] = {-65, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+    
+    /**
+     * flipBit(int n) outside a negative number
+     */
+    public void testFlipBitNegativeOutside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 191;
+        byte rBytes[] = {-1, 127, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+    
+    /**
+     * flipBit(int n) inside a positive number
+     */
+    public void testFlipBitPositiveInside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 15;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, -93, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * flipBit(int n) inside a positive number
+     */
+    public void testFlipBitPositiveInside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 45;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 13, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * flipBit(int n) outside a positive number
+     */
+    public void testFlipBitPositiveOutside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 150;
+        byte rBytes[] = {64, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * flipBit(int n) outside a positive number
+     */
+    public void testFlipBitPositiveOutside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 191;
+        byte rBytes[] = {0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.flipBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * setBit(int n) of a negative n
+     */
+    public void testSetBitException() {
+        byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = -7;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        try {
+            aNumber.setBit(number);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+        }
+    }
+
+    /**
+     * setBit(int n) outside zero
+     */
+    public void testSetBitZero() {
+        byte aBytes[] = {0};
+        int aSign = 0;
+        int number = 0;
+        byte rBytes[] = {1};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * setBit(int n) outside zero
+     */
+    public void testSetBitZeroOutside1() {
+        byte aBytes[] = {0};
+        int aSign = 0;
+        int number = 95;
+        byte rBytes[] = {0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * setBit(int n) inside a positive number
+     */
+    public void testSetBitPositiveInside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 20;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * setBit(int n) inside a positive number
+     */
+    public void testSetBitPositiveInside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 17;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -13, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * setBit(int n) inside a positive number
+     */
+    public void testSetBitPositiveInside3() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 45;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * setBit(int n) inside a positive number
+     */
+    public void testSetBitPositiveInside4 () {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 50;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 93, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * setBit(int n) outside a positive number
+     */
+    public void testSetBitPositiveOutside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 150;
+        byte rBytes[] = {64, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * setBit(int n) outside a positive number
+     */
+    public void testSetBitPositiveOutside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 223;
+        byte rBytes[] = {0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * setBit(int n) the leftmost bit in a positive number
+     */
+    public void testSetBitTopPositive() {
+        byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+        int aSign = 1;
+        int number = 63;
+        byte rBytes[] = {0, -128, 1, -128, 56, 100, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * setBit(int n) the leftmost bit in a negative number
+     */
+    public void testSetBitLeftmostNegative() {
+        byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+        int aSign = -1;
+        int number = 48;
+        byte rBytes[] = {-1, 127, -57, -101, 14, -36, -26, 49};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+    
+    /**
+     * setBit(int n) inside a negative number
+     */
+    public void testSetBitNegativeInside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 15;
+        byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * setBit(int n) inside a negative number
+     */
+    public void testSetBitNegativeInside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 44;
+        byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * setBit(int n) inside a negative number with all ones in bit representation
+     */
+    public void testSetBitNegativeInside3() {
+        String as = "-18446744073709551615";
+        String res = "-18446744073709551611";
+        int number = 2;
+        BigInteger aNumber = new BigInteger(as);
+        BigInteger result = aNumber.setBit(number);
+        assertEquals(res, result.toString());
+    }
+
+    /**
+     * setBit(0) in the negative number of length 1
+     * with all ones in bit representation.
+     * the resulting number's length is 2.
+     */
+    public void testSetBitNegativeInside4() {
+        String as = "-4294967295";
+        int number = 0;
+        BigInteger aNumber = new BigInteger(as);
+        BigInteger result = aNumber.setBit(number);
+        assertEquals(as, result.toString());
+    }
+
+    /**
+     * setBit(0) in the negative number of length 2
+     * with all ones in bit representation.
+     * the resulting number's length is 3.
+     */
+    public void testSetBitNegativeInside5() {
+        String as = "-18446744073709551615";
+        int number = 0;
+        BigInteger aNumber = new BigInteger(as);
+        BigInteger result = aNumber.setBit(number);
+        assertEquals(as, result.toString());
+    }
+
+    /**
+     * setBit(int n) outside a negative number
+     */
+    public void testSetBitNegativeOutside1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 150;
+        byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+    
+    /**
+     * setBit(int n) outside a negative number
+     */
+    public void testSetBitNegativeOutside2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 191;
+        byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.setBit(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+    
+    /**
+     * setBit: check the case when the number of bit to be set can be
+     * represented as n * 32 + 31, where n is an arbitrary integer.
+     * Here 191 = 5 * 32 + 31 
+     */
+    public void testSetBitBug1331() {
+        BigInteger result = BigInteger.valueOf(0L).setBit(191);
+        assertEquals("incorrect value", "3138550867693340381917894711603833208051177722232017256448", result.toString());
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * shiftLeft(int n), n = 0
+     */
+    public void testShiftLeft1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 0;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftLeft(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * shiftLeft(int n), n < 0
+     */
+    public void testShiftLeft2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = -27;
+        byte rBytes[] = {48, 7, 12, -97, -42, -117, 37, -85, 96};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftLeft(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * shiftLeft(int n) a positive number, n > 0
+     */
+    public void testShiftLeft3() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 27;
+        byte rBytes[] = {12, 1, -61, 39, -11, -94, -55, 106, -40, 31, -119, 24, -48, 0, 0, 0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftLeft(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * shiftLeft(int n) a positive number, n > 0
+     */
+    public void testShiftLeft4() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 45;
+        byte rBytes[] = {48, 7, 12, -97, -42, -117, 37, -85, 96, 126, 36, 99, 64, 0, 0, 0, 0, 0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftLeft(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * shiftLeft(int n) a negative number, n > 0
+     */
+    public void testShiftLeft5() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 45;
+        byte rBytes[] = {-49, -8, -13, 96, 41, 116, -38, 84, -97, -127, -37, -100, -64, 0, 0, 0, 0, 0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftLeft(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+    
+    /**
+     * shiftRight(int n), n = 0
+     */
+    public void testShiftRight1() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 0;
+        byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftRight(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * shiftRight(int n), n < 0
+     */
+    public void testShiftRight2() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = -27;
+        byte rBytes[] = {12, 1, -61, 39, -11, -94, -55, 106, -40, 31, -119, 24, -48, 0, 0, 0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftRight(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * shiftRight(int n), 0 < n < 32
+     */
+    public void testShiftRight3() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 27;
+        byte rBytes[] = {48, 7, 12, -97, -42, -117, 37, -85, 96};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftRight(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+    
+    /**
+     * shiftRight(int n), n > 32
+     */
+    public void testShiftRight4() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 45;
+        byte rBytes[] = {12, 1, -61, 39, -11, -94, -55};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftRight(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * shiftRight(int n), n is greater than bitLength()
+     */
+    public void testShiftRight5() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 300;
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftRight(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+    
+    /**
+     * shiftRight a negative number;
+     * shift distance is multiple of 32;
+     * shifted bits are NOT zeroes. 
+     */
+    public void testShiftRightNegNonZeroesMul32() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 1, 0, 0, 0, 0, 0, 0, 0};
+        int aSign = -1;
+        int number = 64;
+        byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftRight(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * shiftRight a negative number;
+     * shift distance is NOT multiple of 32;
+     * shifted bits are NOT zeroes. 
+     */
+    public void testShiftRightNegNonZeroes() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 0, 0, 0, 0, 0, 0, 0, 0};
+        int aSign = -1;
+        int number = 68;
+        byte rBytes[] = {-25, -4, 121, -80, 20, -70, 109, 42};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftRight(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * shiftRight a negative number;
+     * shift distance is NOT multiple of 32;
+     * shifted bits are zeroes. 
+     */
+    public void testShiftRightNegZeroes() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+        int aSign = -1;
+        int number = 68;
+        byte rBytes[] = {-25, -4, 121, -80, 20, -70, 109, 48};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftRight(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * shiftRight a negative number;
+     * shift distance is multiple of 32;
+     * shifted bits are zeroes. 
+     */
+    public void testShiftRightNegZeroesMul32() {
+        byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 0, 0, 0, 0, 0, 0, 0, 0};
+        int aSign = -1;
+        int number = 64;
+        byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -91};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger result = aNumber.shiftRight(number);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * testBit(int n) of a negative n
+     */
+    public void testTestBitException() {
+        byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = -7;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        try {
+            aNumber.testBit(number);
+            fail("ArithmeticException has not been caught");
+        } catch (ArithmeticException e) {
+        }
+    }
+
+    /**
+     * testBit(int n) of a positive number
+     */
+    public void testTestBitPositive1() {
+        byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 7;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertTrue(!aNumber.testBit(number));
+    }
+
+    /**
+     * testBit(int n) of a positive number
+     */
+    public void testTestBitPositive2() {
+        byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 45;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertTrue(aNumber.testBit(number));
+    }
+    
+    /**
+     * testBit(int n) of a positive number, n > bitLength()
+     */
+    public void testTestBitPositive3() {
+        byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = 1;
+        int number = 300;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertTrue(!aNumber.testBit(number));
+    }
+
+    /**
+     * testBit(int n) of a negative number
+     */
+    public void testTestBitNegative1() {
+        byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 7;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertTrue(aNumber.testBit(number));
+    }
+
+    /**
+     * testBit(int n) of a positive n
+     */
+    public void testTestBitNegative2() {
+        byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 45;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertTrue(!aNumber.testBit(number));
+    }
+    
+    /**
+     * testBit(int n) of a positive n, n > bitLength()
+     */
+    public void testTestBitNegative3() {
+        byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+        int aSign = -1;
+        int number = 300;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        assertTrue(aNumber.testBit(number));
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOrTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOrTest.java
new file mode 100644
index 0000000..3509643
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOrTest.java
@@ -0,0 +1,419 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:  java.math.BigInteger
+ * Method: or 
+ */
+public class BigIntegerOrTest extends TestCase {
+    /**
+     * Or for zero and a positive number
+     */
+    public void testZeroPos() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 0;
+        int bSign = 1;        
+        byte rBytes[] = {0, -2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Or for zero and a negative number
+     */
+    public void testZeroNeg() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 0;
+        int bSign = -1;        
+        byte rBytes[] = {-1, 1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Or for a positive number and zero 
+     */
+    public void testPosZero() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {0};
+        int aSign = 1;
+        int bSign = 0;        
+        byte rBytes[] = {0, -2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Or for a negative number and zero  
+     */
+    public void testNegPos() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {0};
+        int aSign = -1;
+        int bSign = 0;        
+        byte rBytes[] = {-1, 1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Or for zero and zero
+     */
+    public void testZeroZero() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {0};
+        int aSign = 0;
+        int bSign = 0;        
+        byte rBytes[] = {0};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 0, result.signum());
+    }
+
+    /**
+     * Or for zero and one
+     */
+    public void testZeroOne() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {1};
+        int aSign = 0;
+        int bSign = 1;        
+        byte rBytes[] = {1};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Or for one and one
+     */
+    public void testOneOne() {
+        byte aBytes[] = {1};
+        byte bBytes[] = {1};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {1};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Or for two positive numbers of the same length
+     */
+    public void testPosPosSameLength() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -2, -3, -4, -4, -1, -66, 95, 47, 123, 59, -13, 39, 30, -97};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Or for two positive numbers; the first is longer
+     */
+    public void testPosPosFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -128, 9, 56, 100, -2, -3, -3, -3, 95, 15, -9, 39, 58, -69, 87, 87, -17, -73};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Or for two positive numbers; the first is shorter
+     */
+    public void testPosPosFirstShorter() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {0, -128, 9, 56, 100, -2, -3, -3, -3, 95, 15, -9, 39, 58, -69, 87, 87, -17, -73};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", 1, result.signum());
+    }
+
+    /**
+     * Or for two negative numbers of the same length
+     */
+    public void testNegNegSameLength() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-1, 127, -57, -101, -5, -5, -18, -38, -17, -2, -65, -2, -11, -3};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Or for two negative numbers; the first is longer
+     */
+    public void testNegNegFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-1, 1, 75, -89, -45, -2, -3, -18, -36, -17, -10, -3, -6, -7, -21};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Or for two negative numbers; the first is shorter
+     */
+    public void testNegNegFirstShorter() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-1, 1, 75, -89, -45, -2, -3, -18, -36, -17, -10, -3, -6, -7, -21};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Or for two numbers of different signs and the same length
+     */
+    public void testPosNegSameLength() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {-1, 1, -126, 59, 103, -2, -11, -7, -3, -33, -57, -3, -5, -5, -21};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Or for two numbers of different signs and the same length
+     */
+    public void testNegPosSameLength() {
+        byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-1, 5, 79, -73, -9, -76, -3, 78, -35, -17, 119};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Or for a negative and a positive numbers; the first is longer
+     */
+    public void testNegPosFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-1, 127, -10, -57, -101, -1, -1, -2, -2, -91, -2, 31, -1, -11, 125, -22, -83, 30, 95};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Or for two negative numbers; the first is shorter
+     */
+    public void testNegPosFirstShorter() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-74, 91, 47, -5, -13, -7, -5, -33, -49, -65, -1, -9, -3};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Or for a positive and a negative numbers; the first is longer
+     */
+    public void testPosNegFirstLonger() {
+        byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {-74, 91, 47, -5, -13, -7, -5, -33, -49, -65, -1, -9, -3};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+
+    /**
+     * Or for a positive and a negative number; the first is shorter
+     */
+    public void testPosNegFirstShorter() {
+        byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {-1, 127, -10, -57, -101, -1, -1, -2, -2, -91, -2, 31, -1, -11, 125, -22, -83, 30, 95};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.or(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals("incorrect sign", -1, result.signum());
+    }
+    
+    public void testRegression() {
+        // Regression test for HARMONY-1996
+        BigInteger x = new BigInteger("-1023");
+        BigInteger r1 = x.and((BigInteger.ZERO.not()).shiftLeft(32));
+        BigInteger r3 = x.and((BigInteger.ZERO.not().shiftLeft(32) ).not());
+        BigInteger result = r1.or(r3);
+        assertEquals(x, result);
+    } 
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerSubtractTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerSubtractTest.java
new file mode 100644
index 0000000..aaddd39
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerSubtractTest.java
@@ -0,0 +1,547 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:  java.math.BigInteger
+ * Method: subtract 
+ */
+public class BigIntegerSubtractTest extends TestCase {
+    /**
+     * Subtract two positive numbers of the same length.
+     * The first is greater.
+     */
+    public void testCase1() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {9, 18, 27, 36, 45, 54, 63, 9, 18, 27};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+
+    /**
+     * Subtract two positive numbers of the same length.
+     * The second is greater.
+     */
+    public void testCase2() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {-10, -19, -28, -37, -46, -55, -64, -10, -19, -27};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(-1, result.signum());
+    }
+
+    /**
+     * Subtract two numbers of the same length and different signs.
+     * The first is positive.
+     * The first is greater in absolute value.
+     */
+    public void testCase3() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {11, 22, 33, 44, 55, 66, 77, 11, 22, 33};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+
+    /**
+     * Subtract two numbers of the same length and different signs.
+     * The first is positive.
+     * The second is greater in absolute value.
+     */
+    public void testCase4() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {11, 22, 33, 44, 55, 66, 77, 11, 22, 33};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+
+    /**
+     * Subtract two negative numbers of the same length.
+     * The first is greater in absolute value.
+     */
+    public void testCase5() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-10, -19, -28, -37, -46, -55, -64, -10, -19, -27};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(-1, result.signum());
+    }
+
+    /**
+     * Subtract two negative numbers of the same length.
+     * The second is greater in absolute value.
+     */
+    public void testCase6() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {9, 18, 27, 36, 45, 54, 63, 9, 18, 27};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+
+    /**
+     * Subtract two numbers of the same length and different signs.
+     * The first is negative.
+     * The first is greater in absolute value.
+     */
+    public void testCase7() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-12, -23, -34, -45, -56, -67, -78, -12, -23, -33};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(-1, result.signum());
+    }
+
+    /**
+     * Subtract two numbers of the same length and different signs.
+     * The first is negative.
+     * The second is greater in absolute value.
+     */
+    public void testCase8() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-12, -23, -34, -45, -56, -67, -78, -12, -23, -33};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(-1, result.signum());
+    }
+    
+    /**
+     * Subtract two positive numbers of different length.
+     * The first is longer.
+     */
+    public void testCase9() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+    
+    /**
+     * Subtract two positive numbers of different length.
+     * The second is longer.
+     */
+    public void testCase10() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(-1, result.signum());
+    }
+
+    /**
+     * Subtract two numbers of different length and different signs.
+     * The first is positive.
+     * The first is greater in absolute value.
+     */
+    public void testCase11() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+
+    /**
+     * Subtract two numbers of the same length and different signs.
+     * The first is positive.
+     * The second is greater in absolute value.
+     */
+    public void testCase12() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        int aSign = 1;
+        int bSign = -1;        
+        byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+    
+    /**
+     * Subtract two numbers of different length and different signs.
+     * The first is negative.
+     * The first is longer.
+     */
+    public void testCase13() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(-1, result.signum());
+    }
+
+    /**
+     * Subtract two numbers of the same length and different signs.
+     * The first is negative.
+     * The second is longer.
+     */
+    public void testCase14() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = 1;        
+        byte rBytes[] = {-2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(-1, result.signum());
+    }
+
+    /**
+     * Subtract two negative numbers of different length.
+     * The first is longer.
+     */
+    public void testCase15() {
+        byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(-1, result.signum());
+}
+    
+    /**
+     * Subtract two negative numbers of different length.
+     * The second is longer.
+     */
+    public void testCase16() {
+        byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+        byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+        int aSign = -1;
+        int bSign = -1;        
+        byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+    
+    /**
+     * Subtract two positive equal in absolute value numbers.
+     */
+    public void testCase17() {
+        byte aBytes[] = {-120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+        byte bBytes[] = {-120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+        byte rBytes[] = {0};
+        int aSign = 1;
+        int bSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(0, result.signum());
+    }
+
+    /**
+     * Subtract zero from a number.
+     * The number is positive.
+     */
+    public void testCase18() {
+        byte aBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+        byte bBytes[] = {0};
+        byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+        int aSign = 1;
+        int bSign = 0;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+
+    /**
+     * Subtract a number from zero.
+     * The number is negative.
+     */
+    public void testCase19() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+        byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+        int aSign = 0;
+        int bSign = -1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+
+    /**
+     * Subtract zero from zero.
+     */
+    public void testCase20() {
+        byte aBytes[] = {0};
+        byte bBytes[] = {0};
+        byte rBytes[] = {0};
+        int aSign = 0;
+        int bSign = 0;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(0, result.signum());
+    }
+    
+    /**
+     * Subtract ZERO from a number.
+     * The number is positive.
+     */
+    public void testCase21() {
+        byte aBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+        byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+        int aSign = 1;
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = BigInteger.ZERO;
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+
+    /**
+     * Subtract a number from ZERO.
+     * The number is negative.
+     */
+    public void testCase22() {
+        byte bBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+        byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+        int bSign = -1;
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(1, result.signum());
+    }
+
+    /**
+     * Subtract ZERO from ZERO.
+     */
+    public void testCase23() {
+        byte rBytes[] = {0};
+        BigInteger aNumber = BigInteger.ZERO;
+        BigInteger bNumber = BigInteger.ZERO;
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(0, result.signum());
+    }
+
+    /**
+     * Subtract ONE from ONE.
+     */
+    public void testCase24() {
+        byte rBytes[] = {0};
+        BigInteger aNumber = BigInteger.ONE;
+        BigInteger bNumber = BigInteger.ONE;
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(0, result.signum());
+    }
+
+    /**
+     * Subtract two numbers so that borrow is 1.
+     */
+    public void testCase25() {
+        byte aBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+        byte bBytes[] = {-128, -128, -128, -128, -128, -128, -128, -128, -128};
+        int aSign = 1;
+        int bSign = 1;        
+        byte rBytes[] = {-128, 127, 127, 127, 127, 127, 127, 127, 127};
+        BigInteger aNumber = new BigInteger(aSign, aBytes);
+        BigInteger bNumber = new BigInteger(bSign, bBytes);
+        BigInteger result = aNumber.subtract(bNumber);
+        byte resBytes[] = new byte[rBytes.length];
+        resBytes = result.toByteArray();
+        for(int i = 0; i < resBytes.length; i++) {
+            assertTrue(resBytes[i] == rBytes[i]);
+        }
+        assertEquals(-1, result.signum());
+    }
+}
+
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerToStringTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerToStringTest.java
new file mode 100644
index 0000000..3f20414
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerToStringTest.java
@@ -0,0 +1,152 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+
+/**
+ * Class:   java.math.BigInteger
+ * Method: toString(int radix)
+ */
+public class BigIntegerToStringTest extends TestCase {
+    /**
+     * If 36 < radix < 2 it should be set to 10
+     */
+    public void testRadixOutOfRange() {
+        String value = "442429234853876401";
+        int radix = 10;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(45);
+        assertTrue(result.equals(value));
+    }
+
+    /**
+     * test negative number of radix 2
+     */
+    public void testRadix2Neg() {
+        String value = "-101001100010010001001010101110000101010110001010010101010101010101010101010101010101010101010010101";
+        int radix = 2;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(radix);
+        assertTrue(result.equals(value));
+    }
+
+    /**
+     * test positive number of radix 2
+     */
+    public void testRadix2Pos() {
+        String value = "101000011111000000110101010101010101010001001010101010101010010101010101010000100010010";
+        int radix = 2;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(radix);
+        assertTrue(result.equals(value));
+    }
+
+    /**
+     * test negative number of radix 10
+     */
+    public void testRadix10Neg() {
+        String value = "-2489756308572364789878394872984";
+        int radix = 16;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(radix);
+        assertTrue(result.equals(value));
+    }
+
+    /**
+     * test positive number of radix 10
+     */
+    public void testRadix10Pos() {
+        String value = "2387627892347567398736473476";
+        int radix = 16;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(radix);
+        assertTrue(result.equals(value));
+    }
+
+    /**
+     * test negative number of radix 16
+     */
+    public void testRadix16Neg() {
+        String value = "-287628a883451b800865c67e8d7ff20";
+        int radix = 16;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(radix);
+        assertTrue(result.equals(value));
+    }
+
+    /**
+     * test positive number of radix 16
+     */
+    public void testRadix16Pos() {
+        String value = "287628a883451b800865c67e8d7ff20";
+        int radix = 16;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(radix);
+        assertTrue(result.equals(value));
+    }
+
+    /**
+     * test negative number of radix 24
+     */
+    public void testRadix24Neg() {
+        String value = "-287628a88gmn3451b8ijk00865c67e8d7ff20";
+        int radix = 24;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(radix);
+        assertTrue(result.equals(value));
+    }
+
+    /**
+     * test positive number of radix 24
+     */
+    public void testRadix24Pos() {
+        String value = "287628a883451bg80ijhk0865c67e8d7ff20";
+        int radix = 24;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(radix);
+        assertTrue(result.equals(value));
+    }
+
+    /**
+     * test negative number of radix 24
+     */
+    public void testRadix36Neg() {
+        String value = "-uhguweut98iu4h3478tq3985pq98yeiuth33485yq4aiuhalai485yiaehasdkr8tywi5uhslei8";
+        int radix = 36;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(radix);
+        assertTrue(result.equals(value));
+    }
+
+    /**
+     * test positive number of radix 24
+     */
+    public void testRadix36Pos() {
+        String value = "23895lt45y6vhgliuwhgi45y845htsuerhsi4586ysuerhtsio5y68peruhgsil4568ypeorihtse48y6";
+        int radix = 36;
+        BigInteger aNumber = new BigInteger(value, radix);
+        String result = aNumber.toString(radix);
+        assertTrue(result.equals(value));
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerXorTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerXorTest.java
new file mode 100644
index 0000000..57ca78a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerXorTest.java
@@ -0,0 +1,277 @@
+/*
+ *  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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class:  java.math.BigInteger
+ * Method: xor
+ */
+public class BigIntegerXorTest extends TestCase {
+	/**
+     * Xor for zero and a positive number
+     */
+    public void testZeroPos() {
+        String numA = "0";
+        String numB = "27384627835298756289327365";
+        String res = "27384627835298756289327365";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for zero and a negative number
+     */
+    public void testZeroNeg() {
+        String numA = "0";
+        String numB = "-27384627835298756289327365";
+        String res = "-27384627835298756289327365";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for a positive number and zero 
+     */
+    public void testPosZero() {
+        String numA = "27384627835298756289327365";
+        String numB = "0";
+        String res = "27384627835298756289327365";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for a negative number and zero  
+     */
+    public void testNegPos() {
+        String numA = "-27384627835298756289327365";
+        String numB = "0";
+        String res = "-27384627835298756289327365";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for zero and zero
+     */
+    public void testZeroZero() {
+        String numA = "0";
+        String numB = "0";
+        String res = "0";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for zero and one
+     */
+    public void testZeroOne() {
+        String numA = "0";
+        String numB = "1";
+        String res = "1";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for one and one
+     */
+    public void testOneOne() {
+        String numA = "1";
+        String numB = "1";
+        String res = "0";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for two positive numbers of the same length
+     */
+    public void testPosPosSameLength() {
+        String numA = "283746278342837476784564875684767";
+        String numB = "293478573489347658763745839457637";
+        String res = "71412358434940908477702819237626";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for two positive numbers; the first is longer
+     */
+    public void testPosPosFirstLonger() {
+        String numA = "2837462783428374767845648748973847593874837948575684767";
+        String numB = "293478573489347658763745839457637";
+        String res = "2837462783428374767845615168483972194300564226167553530";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for two positive numbers; the first is shorter
+     */
+    public void testPosPosFirstShorter() {
+        String numA = "293478573489347658763745839457637";
+        String numB = "2837462783428374767845648748973847593874837948575684767";
+        String res = "2837462783428374767845615168483972194300564226167553530";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for two negative numbers of the same length
+     */
+    public void testNegNegSameLength() {
+        String numA = "-283746278342837476784564875684767";
+        String numB = "-293478573489347658763745839457637";
+        String res = "71412358434940908477702819237626";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for two negative numbers; the first is longer
+     */
+    public void testNegNegFirstLonger() {
+        String numA = "-2837462783428374767845648748973847593874837948575684767";
+        String numB = "-293478573489347658763745839457637";
+        String res = "2837462783428374767845615168483972194300564226167553530";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for two negative numbers; the first is shorter
+     */
+    public void testNegNegFirstShorter() {
+        String numA = "293478573489347658763745839457637";
+        String numB = "2837462783428374767845648748973847593874837948575684767";
+        String res = "2837462783428374767845615168483972194300564226167553530";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for two numbers of different signs and the same length
+     */
+    public void testPosNegSameLength() {
+        String numA = "283746278342837476784564875684767";
+        String numB = "-293478573489347658763745839457637";
+        String res = "-71412358434940908477702819237628";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for two numbers of different signs and the same length
+     */
+    public void testNegPosSameLength() {
+        String numA = "-283746278342837476784564875684767";
+        String numB = "293478573489347658763745839457637";
+        String res = "-71412358434940908477702819237628";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for a negative and a positive numbers; the first is longer
+     */
+    public void testNegPosFirstLonger() {
+        String numA = "-2837462783428374767845648748973847593874837948575684767";
+        String numB = "293478573489347658763745839457637";
+        String res = "-2837462783428374767845615168483972194300564226167553532";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for two negative numbers; the first is shorter
+     */
+    public void testNegPosFirstShorter() {
+        String numA = "-293478573489347658763745839457637";
+        String numB = "2837462783428374767845648748973847593874837948575684767";
+        String res = "-2837462783428374767845615168483972194300564226167553532";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for a positive and a negative numbers; the first is longer
+     */
+    public void testPosNegFirstLonger() {
+        String numA = "2837462783428374767845648748973847593874837948575684767";
+        String numB = "-293478573489347658763745839457637";
+        String res = "-2837462783428374767845615168483972194300564226167553532";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+
+    /**
+     * Xor for a positive and a negative number; the first is shorter
+     */
+    public void testPosNegFirstShorter() {
+        String numA = "293478573489347658763745839457637";
+        String numB = "-2837462783428374767845648748973847593874837948575684767";
+        String res = "-2837462783428374767845615168483972194300564226167553532";
+        BigInteger aNumber = new BigInteger(numA);
+        BigInteger bNumber = new BigInteger(numB);
+        BigInteger result = aNumber.xor(bNumber);
+        assertTrue(res.equals(result.toString()));
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Matcher2Test.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Matcher2Test.java
new file mode 100644
index 0000000..e84b356
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Matcher2Test.java
@@ -0,0 +1,234 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.tests.java.util.regex;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests Matcher methods
+ */
+@SuppressWarnings("nls")
+public class Matcher2Test extends TestCase {
+    public void test_toString() {
+        Pattern p = Pattern.compile("foo");
+        Matcher m = p.matcher("bar");
+        assertNotNull(m.toString());
+    }
+
+    public void testErrorConditions() throws PatternSyntaxException {
+        // Test match cursors in absence of a match
+        Pattern p = Pattern.compile("foo");
+        Matcher m = p.matcher("bar");
+        assertFalse(m.matches());
+
+        try {
+            m.start();
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            m.end();
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            m.group();
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            m.start(1);
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            m.end(1);
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            m.group(1);
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        // regression test for HARMONY-2418
+        try {
+            m.usePattern(null);
+            fail("IllegalArgumentException expected");
+        } catch (IllegalArgumentException e) {
+            // PASSED
+        }
+    }
+
+    public void testErrorConditions2() throws PatternSyntaxException {
+        // Test match cursors in absence of a match
+        Pattern p = Pattern.compile("(foo[0-9])(bar[a-z])");
+        Matcher m = p.matcher("foo1barzfoo2baryfoozbar5");
+
+        assertTrue(m.find());
+        assertEquals(0, m.start());
+        assertEquals(8, m.end());
+        assertEquals(0, m.start(1));
+        assertEquals(4, m.end(1));
+        assertEquals(4, m.start(2));
+        assertEquals(8, m.end(2));
+
+        try {
+            m.start(3);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            m.end(3);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            m.group(3);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            m.start(-1);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            m.end(-1);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            m.group(-1);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        assertTrue(m.find());
+        assertEquals(8, m.start());
+        assertEquals(16, m.end());
+        assertEquals(8, m.start(1));
+        assertEquals(12, m.end(1));
+        assertEquals(12, m.start(2));
+        assertEquals(16, m.end(2));
+
+        try {
+            m.start(3);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            m.end(3);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            m.group(3);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            m.start(-1);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            m.end(-1);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        try {
+            m.group(-1);
+            fail("IndexOutOfBoundsException expected");
+        } catch (IndexOutOfBoundsException e) {
+        }
+
+        assertFalse(m.find());
+
+        try {
+            m.start(3);
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            m.end(3);
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            m.group(3);
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            m.start(-1);
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            m.end(-1);
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            m.group(-1);
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException e) {
+        }
+    }
+
+    /*
+     * Regression test for HARMONY-997
+     */
+    public void testReplacementBackSlash() {
+        String str = "replace me";
+        String replacedString = "me";
+        String substitutionString = "\\";
+        Pattern pat = Pattern.compile(replacedString);
+        Matcher mat = pat.matcher(str);
+        try {
+            mat.replaceAll(substitutionString);
+            fail("IndexOutOfBoundsException should be thrown");
+        } catch (IndexOutOfBoundsException e) {
+        }
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/MatcherTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/MatcherTest.java
new file mode 100644
index 0000000..98450a4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/MatcherTest.java
@@ -0,0 +1,770 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.tests.java.util.regex;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("nls")
+public class MatcherTest extends TestCase {
+    String[] testPatterns = {
+            "(a|b)*abb",
+            "(1*2*3*4*)*567",
+            "(a|b|c|d)*aab",
+            "(1|2|3|4|5|6|7|8|9|0)(1|2|3|4|5|6|7|8|9|0)*",
+            "(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)*",
+            "(a|b)*(a|b)*A(a|b)*lice.*",
+            "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)(a|b|c|d|e|f|g|h|"
+                    + "i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)*(1|2|3|4|5|6|7|8|9|0)*|while|for|struct|if|do" };
+
+    String[] groupPatterns = { "(a|b)*aabb", "((a)|b)*aabb", "((a|b)*)a(abb)",
+            "(((a)|(b))*)aabb", "(((a)|(b))*)aa(b)b", "(((a)|(b))*)a(a(b)b)" };
+
+    public MatcherTest(String name) {
+        super(name);
+    }
+    
+    public void testRegionsIntInt() {
+        Pattern p = Pattern.compile("x*");
+        Matcher m = p.matcher("axxxxxa");
+        assertFalse(m.matches());
+        
+        m.region(1, 6);
+        assertEquals(1, m.regionStart());
+        assertEquals(6, m.regionEnd());
+        assertTrue(m.matches());
+        
+        try {
+            m.region(1, 0);
+            fail("expected an IOOBE");
+        } catch(IndexOutOfBoundsException e) {
+        }
+        
+        try {
+            m.region(-1, 2);
+            fail("expected an IOOBE");
+        } catch(IndexOutOfBoundsException e) {
+        }
+        
+        try {
+            m.region(10, 11);
+            fail("expected an IOOBE");
+        } catch(IndexOutOfBoundsException e) {
+        }
+        
+        try {
+            m.region(1, 10);
+            fail("expected an IOOBE");
+        } catch(IndexOutOfBoundsException e) {
+        }
+    }
+    
+    public void testAppendReplacement() {
+        Pattern pat = Pattern.compile("XX");
+        Matcher m = pat.matcher("Today is XX-XX-XX ...");
+        StringBuffer sb = new StringBuffer();
+
+        for (int i = 0; m.find(); i++) {
+            m.appendReplacement(sb, new Integer(i * 10 + i).toString());
+        }
+        m.appendTail(sb);
+        assertEquals("Today is 0-11-22 ...", sb.toString());
+    }
+
+    public void testAppendReplacementRef() {
+        Pattern p = Pattern.compile("xx (rur|\\$)");
+        Matcher m = p.matcher("xx $ equals to xx rur.");
+        StringBuffer sb = new StringBuffer();
+        for (int i = 1; m.find(); i *= 30) {
+            String rep = new Integer(i).toString() + " $1";
+            m.appendReplacement(sb, rep);
+        }
+        m.appendTail(sb);
+        assertEquals("1 $ equals to 30 rur.", sb.toString());
+    }
+
+    public void testReplaceAll() {
+        String input = "aabfooaabfooabfoob";
+        String pattern = "a*b";
+        Pattern pat = Pattern.compile(pattern);
+        Matcher mat = pat.matcher(input);
+
+        assertEquals("-foo-foo-foo-", mat.replaceAll("-"));
+    }
+
+    /*
+     * Class under test for Matcher reset(CharSequence)
+     */
+    public void testResetCharSequence() {
+        Pattern p = Pattern.compile("abcd");
+        Matcher m = p.matcher("abcd");
+        assertTrue(m.matches());
+        m.reset("efgh");
+        assertFalse(m.matches());
+        
+        try {
+            m.reset(null);
+            fail("expected a NPE");
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void testAppendSlashes() {
+        Pattern p = Pattern.compile("\\\\");
+        Matcher m = p.matcher("one\\cat\\two\\cats\\in\\the\\yard");
+        StringBuffer sb = new StringBuffer();
+        while (m.find()) {
+            m.appendReplacement(sb, "\\\\");
+        }
+        m.appendTail(sb);
+        assertEquals("one\\cat\\two\\cats\\in\\the\\yard", sb.toString());
+
+    }
+
+    public void testReplaceFirst() {
+        String input = "zzzdogzzzdogzzz";
+        String pattern = "dog";
+        Pattern pat = Pattern.compile(pattern);
+        Matcher mat = pat.matcher(input);
+
+        assertEquals("zzzcatzzzdogzzz", mat.replaceFirst("cat"));
+    }
+
+    public void testPattern() {
+        for (String element : testPatterns) {
+            Pattern test = Pattern.compile(element);
+            assertEquals(test, test.matcher("aaa").pattern());
+        }
+
+        for (String element : testPatterns) {
+            assertEquals(element, Pattern.compile(element).matcher("aaa")
+                    .pattern().toString());
+        }
+    }
+
+    /*
+     * Class under test for Matcher reset()
+     */
+    public void testReset() {
+    }
+
+    /*
+     * Class under test for String group(int)
+     */
+    public void testGroupint() {
+        String positiveTestString = "ababababbaaabb";
+
+        // test IndexOutOfBoundsException
+        // //
+        for (int i = 0; i < groupPatterns.length; i++) {
+            Pattern test = Pattern.compile(groupPatterns[i]);
+            Matcher mat = test.matcher(positiveTestString);
+            mat.matches();
+            try {
+                // groupPattern <index + 1> equals to number of groups
+                // of the specified pattern
+                // //
+                mat.group(i + 2);
+                fail("IndexOutBoundsException expected");
+                mat.group(i + 100);
+                fail("IndexOutBoundsException expected");
+                mat.group(-1);
+                fail("IndexOutBoundsException expected");
+                mat.group(-100);
+                fail("IndexOutBoundsException expected");
+            } catch (IndexOutOfBoundsException iobe) {
+            }
+        }
+
+        String[][] groupResults = { { "a" }, { "a", "a" },
+                { "ababababba", "a", "abb" }, { "ababababba", "a", "a", "b" },
+                { "ababababba", "a", "a", "b", "b" },
+                { "ababababba", "a", "a", "b", "abb", "b" }, };
+
+        for (int i = 0; i < groupPatterns.length; i++) {
+            Pattern test = Pattern.compile(groupPatterns[i]);
+            Matcher mat = test.matcher(positiveTestString);
+            mat.matches();
+            for (int j = 0; j < groupResults[i].length; j++) {
+                assertEquals("i: " + i + " j: " + j, groupResults[i][j], mat
+                        .group(j + 1));
+            }
+
+        }
+
+    }
+
+    public void testGroup() {
+        String positiveTestString = "ababababbaaabb";
+        String negativeTestString = "gjhfgdsjfhgcbv";
+        for (String element : groupPatterns) {
+            Pattern test = Pattern.compile(element);
+            Matcher mat = test.matcher(positiveTestString);
+            mat.matches();
+            // test result
+            assertEquals(positiveTestString, mat.group());
+
+            // test equal to group(0) result
+            assertEquals(mat.group(0), mat.group());
+        }
+
+        for (String element : groupPatterns) {
+            Pattern test = Pattern.compile(element);
+            Matcher mat = test.matcher(negativeTestString);
+            mat.matches();
+            try {
+                mat.group();
+                fail("IllegalStateException expected for <false> matches result");
+            } catch (IllegalStateException ise) {
+            }
+        }
+    }
+
+    public void testGroupPossessive() {
+        Pattern pat = Pattern.compile("((a)|(b))++c");
+        Matcher mat = pat.matcher("aac");
+
+        mat.matches();
+        assertEquals("a", mat.group(1));
+    }
+
+    /*
+     * Class under test for boolean find(int)
+     */
+    public void testFindint() {
+    }
+
+    /*
+     * Class under test for int start(int)
+     */
+    public void testStartint() {
+    }
+
+    /*
+     * Class under test for int end(int)
+     */
+    public void testEndint() {
+    }
+
+    public void testMatchesMisc() {
+        String[][] posSeq = {
+                { "abb", "ababb", "abababbababb", "abababbababbabababbbbbabb" },
+                { "213567", "12324567", "1234567", "213213567",
+                        "21312312312567", "444444567" },
+                { "abcdaab", "aab", "abaab", "cdaab", "acbdadcbaab" },
+                { "213234567", "3458", "0987654", "7689546432", "0398576",
+                        "98432", "5" },
+                {
+                        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
+                        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                                + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" },
+                { "ababbaAabababblice", "ababbaAliceababab", "ababbAabliceaaa",
+                        "abbbAbbbliceaaa", "Alice" },
+                { "a123", "bnxnvgds156", "for", "while", "if", "struct" }
+
+        };
+
+        for (int i = 0; i < testPatterns.length; i++) {
+            Pattern pat = Pattern.compile(testPatterns[i]);
+            for (int j = 0; j < posSeq[i].length; j++) {
+                Matcher mat = pat.matcher(posSeq[i][j]);
+                assertTrue("Incorrect match: " + testPatterns[i] + " vs "
+                        + posSeq[i][j], mat.matches());
+            }
+        }
+    }
+
+    public void testMatchesQuantifiers() {
+        String[] testPatternsSingles = { "a{5}", "a{2,4}", "a{3,}" };
+        String[] testPatternsMultiple = { "((a)|(b)){1,2}abb",
+                "((a)|(b)){2,4}", "((a)|(b)){3,}" };
+
+        String[][] stringSingles = { { "aaaaa", "aaa" },
+                { "aa", "a", "aaa", "aaaaaa", "aaaa", "aaaaa" },
+                { "aaa", "a", "aaaa", "aa" }, };
+
+        String[][] stringMultiples = { { "ababb", "aba" },
+                { "ab", "b", "bab", "ababa", "abba", "abababbb" },
+                { "aba", "b", "abaa", "ba" }, };
+
+        for (int i = 0; i < testPatternsSingles.length; i++) {
+            Pattern pat = Pattern.compile(testPatternsSingles[i]);
+            for (int j = 0; j < stringSingles.length / 2; j++) {
+                assertTrue("Match expected, but failed: " + pat.pattern()
+                        + " : " + stringSingles[i][j], pat.matcher(
+                        stringSingles[i][j * 2]).matches());
+                assertFalse("Match failure expected, but match succeed: "
+                        + pat.pattern() + " : " + stringSingles[i][j * 2 + 1],
+                        pat.matcher(stringSingles[i][j * 2 + 1]).matches());
+            }
+        }
+
+        for (int i = 0; i < testPatternsMultiple.length; i++) {
+            Pattern pat = Pattern.compile(testPatternsMultiple[i]);
+            for (int j = 0; j < stringMultiples.length / 2; j++) {
+                assertTrue("Match expected, but failed: " + pat.pattern()
+                        + " : " + stringMultiples[i][j], pat.matcher(
+                        stringMultiples[i][j * 2]).matches());
+                assertFalse(
+                        "Match failure expected, but match succeed: "
+                                + pat.pattern() + " : "
+                                + stringMultiples[i][j * 2 + 1], pat.matcher(
+                                stringMultiples[i][j * 2 + 1]).matches());
+            }
+        }
+    }
+
+    public void testQuantVsGroup() {
+        String patternString = "(d{1,3})((a|c)*)(d{1,3})((a|c)*)(d{1,3})";
+        String testString = "dacaacaacaaddaaacaacaaddd";
+
+        Pattern pat = Pattern.compile(patternString);
+        Matcher mat = pat.matcher(testString);
+
+        mat.matches();
+        assertEquals("dacaacaacaaddaaacaacaaddd", mat.group());
+        assertEquals("d", mat.group(1));
+        assertEquals("acaacaacaa", mat.group(2));
+        assertEquals("dd", mat.group(4));
+        assertEquals("aaacaacaa", mat.group(5));
+        assertEquals("ddd", mat.group(7));
+    }
+
+    public void testLookingAt() {
+    }
+
+    /*
+     * Class under test for boolean find()
+     */
+    public void testFind() {
+        String testPattern = "(abb)";
+        String testString = "cccabbabbabbabbabb";
+        Pattern pat = Pattern.compile(testPattern);
+        Matcher mat = pat.matcher(testString);
+        int start = 3;
+        int end = 6;
+        while (mat.find()) {
+            assertEquals(start, mat.start(1));
+            assertEquals(end, mat.end(1));
+
+            start = end;
+            end += 3;
+        }
+
+        testPattern = "(\\d{1,3})";
+        testString = "aaaa123456789045";
+
+        Pattern pat2 = Pattern.compile(testPattern);
+        Matcher mat2 = pat2.matcher(testString);
+        start = 4;
+        int length = 3;
+        while (mat2.find()) {
+            assertEquals(testString.substring(start, start + length), mat2
+                    .group(1));
+            start += length;
+        }
+    }
+
+    public void testSEOLsymbols() {
+        Pattern pat = Pattern.compile("^a\\(bb\\[$");
+        Matcher mat = pat.matcher("a(bb[");
+
+        assertTrue(mat.matches());
+    }
+
+    /*
+     * Class under test for int start()
+     */
+    public void testStart() {
+    }
+
+    public void testGroupCount() {
+        for (int i = 0; i < groupPatterns.length; i++) {
+            Pattern test = Pattern.compile(groupPatterns[i]);
+            Matcher mat = test.matcher("ababababbaaabb");
+            mat.matches();
+            assertEquals(i + 1, mat.groupCount());
+
+        }
+    }
+
+    public void testRelactantQuantifiers() {
+        Pattern pat = Pattern.compile("(ab*)*b");
+        Matcher mat = pat.matcher("abbbb");
+
+        if (mat.matches()) {
+            assertEquals("abbb", mat.group(1));
+        } else {
+            fail("Match expected: (ab*)*b vs abbbb");
+        }
+    }
+
+    public void testEnhancedFind() {
+        String input = "foob";
+        String pattern = "a*b";
+        Pattern pat = Pattern.compile(pattern);
+        Matcher mat = pat.matcher(input);
+
+        mat.find();
+        assertEquals("b", mat.group());
+    }
+
+    public void testPosCompositeGroup() {
+        String[] posExamples = { "aabbcc", "aacc", "bbaabbcc" };
+        String[] negExamples = { "aabb", "bb", "bbaabb" };
+        Pattern posPat = Pattern.compile("(aa|bb){1,3}+cc");
+        Pattern negPat = Pattern.compile("(aa|bb){1,3}+bb");
+
+        Matcher mat;
+        for (String element : posExamples) {
+            mat = posPat.matcher(element);
+            assertTrue(mat.matches());
+        }
+
+        for (String element : negExamples) {
+            mat = negPat.matcher(element);
+            assertFalse(mat.matches());
+        }
+
+        assertTrue(Pattern.matches("(aa|bb){1,3}+bb", "aabbaabb"));
+
+    }
+
+    public void testPosAltGroup() {
+        String[] posExamples = { "aacc", "bbcc", "cc" };
+        String[] negExamples = { "bb", "aa" };
+        Pattern posPat = Pattern.compile("(aa|bb)?+cc");
+        Pattern negPat = Pattern.compile("(aa|bb)?+bb");
+
+        Matcher mat;
+        for (String element : posExamples) {
+            mat = posPat.matcher(element);
+            assertTrue(posPat.toString() + " vs: " + element, mat.matches());
+        }
+
+        for (String element : negExamples) {
+            mat = negPat.matcher(element);
+            assertFalse(mat.matches());
+        }
+
+        assertTrue(Pattern.matches("(aa|bb)?+bb", "aabb"));
+    }
+
+    public void testRelCompGroup() {
+
+        Matcher mat;
+        Pattern pat;
+        String res = "";
+        for (int i = 0; i < 4; i++) {
+            pat = Pattern.compile("((aa|bb){" + i + ",3}?).*cc");
+            mat = pat.matcher("aaaaaacc");
+            assertTrue(pat.toString() + " vs: " + "aaaaaacc", mat.matches());
+            assertEquals(res, mat.group(1));
+            res += "aa";
+        }
+    }
+
+    public void testRelAltGroup() {
+
+        Matcher mat;
+        Pattern pat;
+
+        pat = Pattern.compile("((aa|bb)??).*cc");
+        mat = pat.matcher("aacc");
+        assertTrue(pat.toString() + " vs: " + "aacc", mat.matches());
+        assertEquals("", mat.group(1));
+
+        pat = Pattern.compile("((aa|bb)??)cc");
+        mat = pat.matcher("aacc");
+        assertTrue(pat.toString() + " vs: " + "aacc", mat.matches());
+        assertEquals("aa", mat.group(1));
+    }
+
+    public void testIgnoreCase() {
+        Pattern pat = Pattern.compile("(aa|bb)*", Pattern.CASE_INSENSITIVE);
+        Matcher mat = pat.matcher("aAbb");
+
+        assertTrue(mat.matches());
+
+        pat = Pattern.compile("(a|b|c|d|e)*", Pattern.CASE_INSENSITIVE);
+        mat = pat.matcher("aAebbAEaEdebbedEccEdebbedEaedaebEbdCCdbBDcdcdADa");
+        assertTrue(mat.matches());
+
+        pat = Pattern.compile("[a-e]*", Pattern.CASE_INSENSITIVE);
+        mat = pat.matcher("aAebbAEaEdebbedEccEdebbedEaedaebEbdCCdbBDcdcdADa");
+        assertTrue(mat.matches());
+
+    }
+
+    public void testQuoteReplacement() {
+        assertEquals("\\\\aaCC\\$1", Matcher.quoteReplacement("\\aaCC$1"));
+    }
+
+    public void testOverFlow() {
+        Pattern tp = Pattern.compile("(a*)*");
+        Matcher tm = tp.matcher("aaa");
+        assertTrue(tm.matches());
+        assertEquals("", tm.group(1));
+
+        assertTrue(Pattern.matches("(1+)\\1+", "11"));
+        assertTrue(Pattern.matches("(1+)(2*)\\2+", "11"));
+
+        Pattern pat = Pattern.compile("(1+)\\1*");
+        Matcher mat = pat.matcher("11");
+
+        assertTrue(mat.matches());
+        assertEquals("11", mat.group(1));
+
+        pat = Pattern.compile("((1+)|(2+))(\\2+)");
+        mat = pat.matcher("11");
+
+        assertTrue(mat.matches());
+        assertEquals("1", mat.group(2));
+        assertEquals("1", mat.group(1));
+        assertEquals("1", mat.group(4));
+        assertNull(mat.group(3));
+
+    }
+
+    public void testUnicode() {
+
+        assertTrue(Pattern.matches("\\x61a", "aa"));
+        assertTrue(Pattern.matches("\\u0061a", "aa"));
+        assertTrue(Pattern.matches("\\0141a", "aa"));
+        assertTrue(Pattern.matches("\\0777", "?7"));
+
+    }
+
+    public void testUnicodeCategory() {
+        assertTrue(Pattern.matches("\\p{Ll}", "k")); // Unicode lower case
+        assertTrue(Pattern.matches("\\P{Ll}", "K")); // Unicode non-lower
+        // case
+        assertTrue(Pattern.matches("\\p{Lu}", "K")); // Unicode upper case
+        assertTrue(Pattern.matches("\\P{Lu}", "k")); // Unicode non-upper
+        // case
+        // combinations
+        assertTrue(Pattern.matches("[\\p{L}&&[^\\p{Lu}]]", "k"));
+        assertTrue(Pattern.matches("[\\p{L}&&[^\\p{Ll}]]", "K"));
+        assertFalse(Pattern.matches("[\\p{L}&&[^\\p{Lu}]]", "K"));
+        assertFalse(Pattern.matches("[\\p{L}&&[^\\p{Ll}]]", "k"));
+
+        // category/character combinations
+        assertFalse(Pattern.matches("[\\p{L}&&[^a-z]]", "k"));
+        assertTrue(Pattern.matches("[\\p{L}&&[^a-z]]", "K"));
+
+        assertTrue(Pattern.matches("[\\p{Lu}a-z]", "k"));
+        assertTrue(Pattern.matches("[a-z\\p{Lu}]", "k"));
+
+        assertFalse(Pattern.matches("[\\p{Lu}a-d]", "k"));
+        assertTrue(Pattern.matches("[a-d\\p{Lu}]", "K"));
+
+        // assertTrue(Pattern.matches("[\\p{L}&&[^\\p{Lu}&&[^K]]]", "K"));
+        assertFalse(Pattern.matches("[\\p{L}&&[^\\p{Lu}&&[^G]]]", "K"));
+
+    }
+
+    public void testSplitEmpty() {
+
+        Pattern pat = Pattern.compile("");
+        String[] s = pat.split("", -1);
+
+        assertEquals(1, s.length);
+        assertEquals("", s[0]);
+    }
+
+    public void testFindDollar() {
+        Matcher mat = Pattern.compile("a$").matcher("a\n");
+        assertTrue(mat.find());
+        assertEquals("a", mat.group());
+    }
+
+    /*
+     * Verify if the Matcher can match the input when region is changed
+     */
+    public void testMatchesRegionChanged() {
+        // Regression for HARMONY-610
+        String input = " word ";
+        Pattern pattern = Pattern.compile("\\w+");
+        Matcher matcher = pattern.matcher(input);
+        matcher.region(1, 5);
+        assertTrue(matcher.matches());
+    }
+
+    public void testAllCodePoints_p() {
+        // Regression for HARMONY-3145
+        int[] codePoint = new int[1];
+        Pattern p = Pattern.compile("(\\p{all})+");
+        boolean res = true;
+        int cnt = 0;
+        int step = 16; // Ideally 1, but devices are still too slow.
+        for (int i = 0; i < 0x110000; i += step) {
+            codePoint[0] = i;
+            String s = new String(codePoint, 0, 1);
+            if (!s.matches(p.toString())) {
+                cnt++;
+                res = false;
+            }
+        }
+        assertTrue(res);
+        assertEquals(0, cnt);
+    }
+
+    public void testAllCodePoints_P() {
+        // Regression for HARMONY-3145
+        int[] codePoint = new int[1];
+        Pattern p = Pattern.compile("(\\P{all})+");
+        boolean res = true;
+        int cnt = 0;
+        int step = 16; // Ideally 1, but devices are still too slow.
+        for (int i = 0; i < 0x110000; i += step) {
+            codePoint[0] = i;
+            String s = new String(codePoint, 0, 1);
+            if (!s.matches(p.toString())) {
+                cnt++;
+                res = false;
+            }
+        }
+        assertFalse(res);
+        assertEquals(0x110000 / step, cnt);
+    }
+
+    /*
+     * Verify if the Matcher behaves correct when region is changed
+     */
+    public void testFindRegionChanged() {
+        // Regression for HARMONY-625
+        Pattern pattern = Pattern.compile("(?s).*");
+        Matcher matcher = pattern.matcher("abcde");
+        matcher.find();
+        assertEquals("abcde", matcher.group());
+
+        matcher = pattern.matcher("abcde");
+        matcher.region(0, 2);
+        matcher.find();
+        assertEquals("ab", matcher.group());
+
+    }
+
+    /*
+     * Verify if the Matcher behaves correct with pattern "c" when region is
+     * changed
+     */
+    public void testFindRegionChanged2() {
+        // Regression for HARMONY-713
+        Pattern pattern = Pattern.compile("c");
+
+        String inputStr = "aabb.c";
+        Matcher matcher = pattern.matcher(inputStr);
+        matcher.region(0, 3);
+
+        assertFalse(matcher.find());
+    }
+
+    /*
+     * Regression test for HARMONY-674
+     */
+    public void testPatternMatcher() throws Exception {
+        Pattern pattern = Pattern.compile("(?:\\d+)(?:pt)");
+        assertTrue(pattern.matcher("14pt").matches());
+    }
+
+    /**
+     * Inspired by HARMONY-3360
+     */
+    public void test3360() {
+        String str = "!\"#%&'(),-./";
+        Pattern p = Pattern.compile("\\s");
+        Matcher m = p.matcher(str);
+
+        assertFalse(m.find());
+    }
+
+    /**
+     * Regression test for HARMONY-3360
+     */
+    public void testGeneralPunctuationCategory() {
+        String[] s = { ",", "!", "\"", "#", "%", "&", "'", "(", ")", "-", ".",
+                "/" };
+        String regexp = "\\p{P}";
+
+        for (int i = 0; i < s.length; i++) {
+            Pattern pattern = Pattern.compile(regexp);
+            Matcher matcher = pattern.matcher(s[i]);
+            assertTrue(matcher.find());
+        }
+    }
+
+    /**
+     * Regression test for HARMONY-4396
+     */
+    public void testHitEndAfterFind() {
+        hitEndTest(true, "#01.0", "r((ege)|(geg))x", "regexx", false);
+        hitEndTest(true, "#01.1", "r((ege)|(geg))x", "regex", false);
+        hitEndTest(true, "#01.2", "r((ege)|(geg))x", "rege", true);
+        hitEndTest(true, "#01.2", "r((ege)|(geg))x", "xregexx", false);
+
+        hitEndTest(true, "#02.0", "regex", "rexreger", true);
+        hitEndTest(true, "#02.1", "regex", "raxregexr", false);
+
+        String floatRegex = getHexFloatRegex();
+        hitEndTest(true, "#03.0", floatRegex, Double.toHexString(-1.234d), true);
+        hitEndTest(true, "#03.1", floatRegex, "1 ABC"
+                + Double.toHexString(Double.NaN) + "buhuhu", false);
+        hitEndTest(true, "#03.2", floatRegex, Double.toHexString(-0.0) + "--",
+                false);
+        hitEndTest(true, "#03.3", floatRegex, "--"
+                + Double.toHexString(Double.MIN_VALUE) + "--", false);
+
+        hitEndTest(true, "#04.0", "(\\d+) fish (\\d+) fish (\\w+) fish (\\d+)",
+                "1 fish 2 fish red fish 5", true);
+        hitEndTest(true, "#04.1", "(\\d+) fish (\\d+) fish (\\w+) fish (\\d+)",
+                "----1 fish 2 fish red fish 5----", false);
+    }
+
+    public void testToString() {
+        Matcher m = Pattern.compile("(\\d{1,3})").matcher("aaaa666456789045");
+        assertEquals("java.util.regex.Matcher[pattern=(\\d{1,3}) region=0,16 lastmatch=]", m.toString());
+        assertTrue(m.find());
+        assertEquals("java.util.regex.Matcher[pattern=(\\d{1,3}) region=0,16 lastmatch=666]", m.toString());
+        m.region(4, 8);
+        assertEquals("java.util.regex.Matcher[pattern=(\\d{1,3}) region=4,8 lastmatch=]", m.toString());
+    }
+
+    private void hitEndTest(boolean callFind, String testNo, String regex,
+            String input, boolean hit) {
+        Pattern pattern = Pattern.compile(regex);
+        Matcher matcher = pattern.matcher(input);
+        if (callFind) {
+            matcher.find();
+        } else {
+            matcher.matches();
+        }
+        boolean h = matcher.hitEnd();
+
+        assertTrue(testNo, h == hit);
+    }
+
+    private String getHexFloatRegex() {
+        String hexDecimal = "(-|\\+)?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP](-|\\+)?[0-9]+)?";
+        String notANumber = "((-|\\+)?Infinity)|([nN]a[nN])";
+        return new StringBuilder("((").append(hexDecimal).append(")|(").append(
+                notANumber).append("))").toString();
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ModeTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ModeTest.java
new file mode 100644
index 0000000..c34cebe
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ModeTest.java
@@ -0,0 +1,111 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.tests.java.util.regex;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests Pattern compilation modes and modes triggered in pattern strings
+ */
+@SuppressWarnings("nls")
+public class ModeTest extends TestCase {
+    public void testCase() throws PatternSyntaxException {
+        Pattern p;
+        Matcher m;
+
+        p = Pattern.compile("([a-z]+)[0-9]+");
+        m = p.matcher("cAT123#dog345");
+        assertTrue(m.find());
+        assertEquals("dog", m.group(1));
+        assertFalse(m.find());
+
+        p = Pattern.compile("([a-z]+)[0-9]+", Pattern.CASE_INSENSITIVE);
+        m = p.matcher("cAt123#doG345");
+        assertTrue(m.find());
+        assertEquals("cAt", m.group(1));
+        assertTrue(m.find());
+        assertEquals("doG", m.group(1));
+        assertFalse(m.find());
+
+        p = Pattern.compile("(?i)([a-z]+)[0-9]+");
+        m = p.matcher("cAt123#doG345");
+        assertTrue(m.find());
+        assertEquals("cAt", m.group(1));
+        assertTrue(m.find());
+        assertEquals("doG", m.group(1));
+        assertFalse(m.find());
+    }
+
+    public void testMultiline() throws PatternSyntaxException {
+        Pattern p;
+        Matcher m;
+
+        p = Pattern.compile("^foo");
+        m = p.matcher("foobar");
+        assertTrue(m.find());
+        assertTrue(m.start() == 0 && m.end() == 3);
+        assertFalse(m.find());
+
+        m = p.matcher("barfoo");
+        assertFalse(m.find());
+
+        p = Pattern.compile("foo$");
+        m = p.matcher("foobar");
+        assertFalse(m.find());
+
+        m = p.matcher("barfoo");
+        assertTrue(m.find());
+        assertTrue(m.start() == 3 && m.end() == 6);
+        assertFalse(m.find());
+
+        p = Pattern.compile("^foo([0-9]*)", Pattern.MULTILINE);
+        m = p.matcher("foo1bar\nfoo2foo3\nbarfoo4");
+        assertTrue(m.find());
+        assertEquals("1", m.group(1));
+        assertTrue(m.find());
+        assertEquals("2", m.group(1));
+        assertFalse(m.find());
+
+        p = Pattern.compile("foo([0-9]*)$", Pattern.MULTILINE);
+        m = p.matcher("foo1bar\nfoo2foo3\nbarfoo4");
+        assertTrue(m.find());
+        assertEquals("3", m.group(1));
+        assertTrue(m.find());
+        assertEquals("4", m.group(1));
+        assertFalse(m.find());
+
+        p = Pattern.compile("(?m)^foo([0-9]*)");
+        m = p.matcher("foo1bar\nfoo2foo3\nbarfoo4");
+        assertTrue(m.find());
+        assertEquals("1", m.group(1));
+        assertTrue(m.find());
+        assertEquals("2", m.group(1));
+        assertFalse(m.find());
+
+        p = Pattern.compile("(?m)foo([0-9]*)$");
+        m = p.matcher("foo1bar\nfoo2foo3\nbarfoo4");
+        assertTrue(m.find());
+        assertEquals("3", m.group(1));
+        assertTrue(m.find());
+        assertEquals("4", m.group(1));
+        assertFalse(m.find());
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Pattern2Test.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Pattern2Test.java
new file mode 100644
index 0000000..cf30fc6
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Pattern2Test.java
@@ -0,0 +1,1299 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.tests.java.util.regex;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests simple Pattern compilation and Matcher methods
+ */
+@SuppressWarnings("nls")
+public class Pattern2Test extends TestCase {
+    public void testSimpleMatch() throws PatternSyntaxException {
+        Pattern p = Pattern.compile("foo.*");
+
+        Matcher m1 = p.matcher("foo123");
+        assertTrue(m1.matches());
+        assertTrue(m1.find(0));
+        assertTrue(m1.lookingAt());
+
+        Matcher m2 = p.matcher("fox");
+        assertFalse(m2.matches());
+        assertFalse(m2.find(0));
+        assertFalse(m2.lookingAt());
+
+        assertTrue(Pattern.matches("foo.*", "foo123"));
+        assertFalse(Pattern.matches("foo.*", "fox"));
+
+        assertFalse(Pattern.matches("bar", "foobar"));
+
+        assertTrue(Pattern.matches("", ""));
+    }
+
+    public void testCursors() {
+        Pattern p;
+        Matcher m;
+
+        try {
+            p = Pattern.compile("foo");
+
+            m = p.matcher("foobar");
+            assertTrue(m.find());
+            assertEquals(0, m.start());
+            assertEquals(3, m.end());
+            assertFalse(m.find());
+
+            // Note: also testing reset here
+            m.reset();
+            assertTrue(m.find());
+            assertEquals(0, m.start());
+            assertEquals(3, m.end());
+            assertFalse(m.find());
+
+            m.reset("barfoobar");
+            assertTrue(m.find());
+            assertEquals(3, m.start());
+            assertEquals(6, m.end());
+            assertFalse(m.find());
+
+            m.reset("barfoo");
+            assertTrue(m.find());
+            assertEquals(3, m.start());
+            assertEquals(6, m.end());
+            assertFalse(m.find());
+
+            m.reset("foobarfoobarfoo");
+            assertTrue(m.find());
+            assertEquals(0, m.start());
+            assertEquals(3, m.end());
+            assertTrue(m.find());
+            assertEquals(6, m.start());
+            assertEquals(9, m.end());
+            assertTrue(m.find());
+            assertEquals(12, m.start());
+            assertEquals(15, m.end());
+            assertFalse(m.find());
+            assertTrue(m.find(0));
+            assertEquals(0, m.start());
+            assertEquals(3, m.end());
+            assertTrue(m.find(4));
+            assertEquals(6, m.start());
+            assertEquals(9, m.end());
+        } catch (PatternSyntaxException e) {
+            System.out.println(e.getMessage());
+            fail();
+        }
+    }
+
+    public void testGroups() throws PatternSyntaxException {
+        Pattern p;
+        Matcher m;
+
+        p = Pattern.compile("(p[0-9]*)#?(q[0-9]*)");
+
+        m = p.matcher("p1#q3p2q42p5p71p63#q888");
+        assertTrue(m.find());
+        assertEquals(0, m.start());
+        assertEquals(5, m.end());
+        assertEquals(2, m.groupCount());
+        assertEquals(0, m.start(0));
+        assertEquals(5, m.end(0));
+        assertEquals(0, m.start(1));
+        assertEquals(2, m.end(1));
+        assertEquals(3, m.start(2));
+        assertEquals(5, m.end(2));
+        assertEquals("p1#q3", m.group());
+        assertEquals("p1#q3", m.group(0));
+        assertEquals("p1", m.group(1));
+        assertEquals("q3", m.group(2));
+
+        assertTrue(m.find());
+        assertEquals(5, m.start());
+        assertEquals(10, m.end());
+        assertEquals(2, m.groupCount());
+        assertEquals(10, m.end(0));
+        assertEquals(5, m.start(1));
+        assertEquals(7, m.end(1));
+        assertEquals(7, m.start(2));
+        assertEquals(10, m.end(2));
+        assertEquals("p2q42", m.group());
+        assertEquals("p2q42", m.group(0));
+        assertEquals("p2", m.group(1));
+        assertEquals("q42", m.group(2));
+
+        assertTrue(m.find());
+        assertEquals(15, m.start());
+        assertEquals(23, m.end());
+        assertEquals(2, m.groupCount());
+        assertEquals(15, m.start(0));
+        assertEquals(23, m.end(0));
+        assertEquals(15, m.start(1));
+        assertEquals(18, m.end(1));
+        assertEquals(19, m.start(2));
+        assertEquals(23, m.end(2));
+        assertEquals("p63#q888", m.group());
+        assertEquals("p63#q888", m.group(0));
+        assertEquals("p63", m.group(1));
+        assertEquals("q888", m.group(2));
+        assertFalse(m.find());
+    }
+
+    public void testReplace() throws PatternSyntaxException {
+        Pattern p;
+        Matcher m;
+
+        // Note: examples from book,
+        // Hitchens, Ron, 2002, "Java NIO", O'Reilly, page 171
+        p = Pattern.compile("a*b");
+
+        m = p.matcher("aabfooaabfooabfoob");
+        assertTrue(m.replaceAll("-").equals("-foo-foo-foo-"));
+        assertTrue(m.replaceFirst("-").equals("-fooaabfooabfoob"));
+
+        /*
+         * p = Pattern.compile ("\\p{Blank}");
+         * 
+         * m = p.matcher ("fee fie foe fum"); assertTrue
+         * (m.replaceFirst("-").equals ("fee-fie foe fum")); assertTrue
+         * (m.replaceAll("-").equals ("fee-fie-foe-fum"));
+         */
+
+        p = Pattern.compile("([bB])yte");
+
+        m = p.matcher("Byte for byte");
+        assertTrue(m.replaceFirst("$1ite").equals("Bite for byte"));
+        assertTrue(m.replaceAll("$1ite").equals("Bite for bite"));
+
+        p = Pattern.compile("\\d\\d\\d\\d([- ])");
+
+        m = p.matcher("card #1234-5678-1234");
+        assertTrue(m.replaceFirst("xxxx$1").equals("card #xxxx-5678-1234"));
+        assertTrue(m.replaceAll("xxxx$1").equals("card #xxxx-xxxx-1234"));
+
+        p = Pattern.compile("(up|left)( *)(right|down)");
+
+        m = p.matcher("left right, up down");
+        assertTrue(m.replaceFirst("$3$2$1").equals("right left, up down"));
+        assertTrue(m.replaceAll("$3$2$1").equals("right left, down up"));
+
+        p = Pattern.compile("([CcPp][hl]e[ea]se)");
+
+        m = p.matcher("I want cheese. Please.");
+        assertTrue(m.replaceFirst("<b> $1 </b>").equals(
+                "I want <b> cheese </b>. Please."));
+        assertTrue(m.replaceAll("<b> $1 </b>").equals(
+                "I want <b> cheese </b>. <b> Please </b>."));
+    }
+
+    public void testEscapes() throws PatternSyntaxException {
+        Pattern p;
+        Matcher m;
+
+        // Test \\ sequence
+        p = Pattern.compile("([a-z]+)\\\\([a-z]+);");
+        m = p.matcher("fred\\ginger;abbott\\costello;jekell\\hyde;");
+        assertTrue(m.find());
+        assertEquals("fred", m.group(1));
+        assertEquals("ginger", m.group(2));
+        assertTrue(m.find());
+        assertEquals("abbott", m.group(1));
+        assertEquals("costello", m.group(2));
+        assertTrue(m.find());
+        assertEquals("jekell", m.group(1));
+        assertEquals("hyde", m.group(2));
+        assertFalse(m.find());
+
+        // Test \n, \t, \r, \f, \e, \a sequences
+        p = Pattern.compile("([a-z]+)[\\n\\t\\r\\f\\e\\a]+([a-z]+)");
+        m = p.matcher("aa\nbb;cc\u0009\rdd;ee\u000C\u001Bff;gg\n\u0007hh");
+        assertTrue(m.find());
+        assertEquals("aa", m.group(1));
+        assertEquals("bb", m.group(2));
+        assertTrue(m.find());
+        assertEquals("cc", m.group(1));
+        assertEquals("dd", m.group(2));
+        assertTrue(m.find());
+        assertEquals("ee", m.group(1));
+        assertEquals("ff", m.group(2));
+        assertTrue(m.find());
+        assertEquals("gg", m.group(1));
+        assertEquals("hh", m.group(2));
+        assertFalse(m.find());
+
+        // Test \\u and \\x sequences
+p = Pattern.compile("([0-9]+)[\\u0020:\\x21];");
+        m = p.matcher("11:;22 ;33-;44!;");
+        assertTrue(m.find());
+        assertEquals("11", m.group(1));
+        assertTrue(m.find());
+        assertEquals("22", m.group(1));
+        assertTrue(m.find());
+        assertEquals("44", m.group(1));
+        assertFalse(m.find());
+
+        // Test invalid unicode sequences
+        try {
+            p = Pattern.compile("\\u");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\u;");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\u002");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\u002;");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        // Test invalid hex sequences
+        try {
+            p = Pattern.compile("\\x");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\x;");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        // icu4c allows 1 to 6 hex digits in \x escapes.
+        p = Pattern.compile("\\xa");
+        p = Pattern.compile("\\xab");
+        p = Pattern.compile("\\xabc");
+        p = Pattern.compile("\\xabcd");
+        p = Pattern.compile("\\xabcde");
+        p = Pattern.compile("\\xabcdef");
+        // (Further digits would just be treated as characters after the escape.)
+        try {
+            p = Pattern.compile("\\xg");
+            fail();
+        } catch (PatternSyntaxException expected) {
+        }
+
+        // Test \0 (octal) sequences (1, 2 and 3 digit)
+        p = Pattern.compile("([0-9]+)[\\07\\040\\0160];");
+        m = p.matcher("11\u0007;22:;33 ;44p;");
+        assertTrue(m.find());
+        assertEquals("11", m.group(1));
+        assertTrue(m.find());
+        assertEquals("33", m.group(1));
+        assertTrue(m.find());
+        assertEquals("44", m.group(1));
+        assertFalse(m.find());
+
+        // Test invalid octal sequences
+        try {
+            p = Pattern.compile("\\08");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        // originally contributed test did not check the result
+        // TODO: check what RI does here
+        // try {
+        // p = Pattern.compile("\\0477");
+        // fail("PatternSyntaxException expected");
+        // } catch (PatternSyntaxException e) {
+        // }
+
+        try {
+            p = Pattern.compile("\\0");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\0;");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        // Test \c (control character) sequence
+        p = Pattern.compile("([0-9]+)[\\cA\\cB\\cC\\cD];");
+        m = p.matcher("11\u0001;22:;33\u0002;44p;55\u0003;66\u0004;");
+        assertTrue(m.find());
+        assertEquals("11", m.group(1));
+        assertTrue(m.find());
+        assertEquals("33", m.group(1));
+        assertTrue(m.find());
+        assertEquals("55", m.group(1));
+        assertTrue(m.find());
+        assertEquals("66", m.group(1));
+        assertFalse(m.find());
+
+        // More thorough control escape test
+        // Ensure that each escape matches exactly the corresponding
+        // character
+        // code and no others (well, from 0-255 at least)
+        int i, j;
+        for (i = 0; i < 26; i++) {
+            p = Pattern.compile("\\c" + Character.toString((char) ('A' + i)));
+            int match_char = -1;
+            for (j = 0; j < 255; j++) {
+                m = p.matcher(Character.toString((char) j));
+                if (m.matches()) {
+                    assertEquals(-1, match_char);
+                    match_char = j;
+                }
+            }
+            assertTrue(match_char == i + 1);
+        }
+
+        // Test invalid control escapes
+        // icu4c 50 accepts this pattern, and treats it as a literal.
+        //try {
+            p = Pattern.compile("\\c");
+            assertTrue(p.matcher("x\\cy").find());
+        //    fail(p.matcher("").toString());
+        //} catch (PatternSyntaxException e) {
+        //}
+
+        // But \cH works.
+        p = Pattern.compile("\\cH");
+        assertTrue(p.matcher("x\u0008y").find());
+        assertFalse(p.matcher("x\\cHy").find());
+
+        // originally contributed test did not check the result
+        // TODO: check what RI does here
+        // try {
+        // p = Pattern.compile("\\c;");
+        // fail("PatternSyntaxException expected");
+        // } catch (PatternSyntaxException e) {
+        // }
+        //
+        // try {
+        // p = Pattern.compile("\\ca;");
+        // fail("PatternSyntaxException expected");
+        // } catch (PatternSyntaxException e) {
+        // }
+        //
+        // try {
+        // p = Pattern.compile("\\c4;");
+        // fail("PatternSyntaxException expected");
+        // } catch (PatternSyntaxException e) {
+        // }
+    }
+
+    public void testCharacterClasses() throws PatternSyntaxException {
+        Pattern p;
+        Matcher m;
+
+        // Test one character range
+        p = Pattern.compile("[p].*[l]");
+        m = p.matcher("paul");
+        assertTrue(m.matches());
+        m = p.matcher("pool");
+        assertTrue(m.matches());
+        m = p.matcher("pong");
+        assertFalse(m.matches());
+        m = p.matcher("pl");
+        assertTrue(m.matches());
+
+        // Test two character range
+        p = Pattern.compile("[pm].*[lp]");
+        m = p.matcher("prop");
+        assertTrue(m.matches());
+        m = p.matcher("mall");
+        assertTrue(m.matches());
+        m = p.matcher("pong");
+        assertFalse(m.matches());
+        m = p.matcher("pill");
+        assertTrue(m.matches());
+
+        // Test range including [ and ]
+        p = Pattern.compile("[<\\[].*[\\]>]");
+        m = p.matcher("<foo>");
+        assertTrue(m.matches());
+        m = p.matcher("[bar]");
+        assertTrue(m.matches());
+        m = p.matcher("{foobar]");
+        assertFalse(m.matches());
+        m = p.matcher("<pill]");
+        assertTrue(m.matches());
+
+        // Test range using ^
+        p = Pattern.compile("[^bc][a-z]+[tr]");
+        m = p.matcher("pat");
+        assertTrue(m.matches());
+        m = p.matcher("liar");
+        assertTrue(m.matches());
+        m = p.matcher("car");
+        assertFalse(m.matches());
+        m = p.matcher("gnat");
+        assertTrue(m.matches());
+
+        // Test character range using -
+        p = Pattern.compile("[a-z]_+[a-zA-Z]-+[0-9p-z]");
+        m = p.matcher("d__F-8");
+        assertTrue(m.matches());
+        m = p.matcher("c_a-q");
+        assertTrue(m.matches());
+        m = p.matcher("a__R-a");
+        assertFalse(m.matches());
+        m = p.matcher("r_____d-----5");
+        assertTrue(m.matches());
+
+        // Test range using unicode characters and unicode and hex escapes
+        p = Pattern.compile("[\\u1234-\\u2345]_+[a-z]-+[\u0001-\\x11]");
+        m = p.matcher("\u2000_q-\u0007");
+        assertTrue(m.matches());
+        m = p.matcher("\u1234_z-\u0001");
+        assertTrue(m.matches());
+        m = p.matcher("r_p-q");
+        assertFalse(m.matches());
+        m = p.matcher("\u2345_____d-----\n");
+        assertTrue(m.matches());
+
+        // Test ranges including the "-" character
+        // "---" collides with icu4c's "--" operator, and likely to be user error anyway.
+        if (false) {
+            p = Pattern.compile("[\\*-/]_+[---]!+[--AP]");
+            m = p.matcher("-_-!!A");
+            assertTrue(m.matches());
+            m = p.matcher("\u002b_-!!!-");
+            assertTrue(m.matches());
+            m = p.matcher("!_-!@");
+            assertFalse(m.matches());
+            m = p.matcher(",______-!!!!!!!P");
+            assertTrue(m.matches());
+        }
+
+        // Test nested ranges
+        p = Pattern.compile("[pm[t]][a-z]+[[r]lp]");
+        m = p.matcher("prop");
+        assertTrue(m.matches());
+        m = p.matcher("tsar");
+        assertTrue(m.matches());
+        m = p.matcher("pong");
+        assertFalse(m.matches());
+        m = p.matcher("moor");
+        assertTrue(m.matches());
+
+        // Test character class intersection with &&
+        // TODO: figure out what x&&y or any class with a null intersection
+        // set (like [[a-c]&&[d-f]]) might mean. It doesn't mean "match
+        // nothing" and doesn't mean "match anything" so I'm stumped.
+        p = Pattern.compile("[[a-p]&&[g-z]]+-+[[a-z]&&q]-+[x&&[a-z]]-+");
+        m = p.matcher("h--q--x--");
+        assertTrue(m.matches());
+        m = p.matcher("hog--q-x-");
+        assertTrue(m.matches());
+        m = p.matcher("ape--q-x-");
+        assertFalse(m.matches());
+        m = p.matcher("mop--q-x----");
+        assertTrue(m.matches());
+
+        // Test error cases with &&
+        // This is an RI bug that icu4c doesn't have.
+        if (false) {
+            p = Pattern.compile("[&&[xyz]]");
+            m = p.matcher("&");
+            // System.out.println(m.matches());
+            m = p.matcher("x");
+            // System.out.println(m.matches());
+            m = p.matcher("y");
+            // System.out.println(m.matches());
+        }
+        p = Pattern.compile("[[xyz]&[axy]]");
+        m = p.matcher("x");
+        // System.out.println(m.matches());
+        m = p.matcher("z");
+        // System.out.println(m.matches());
+        m = p.matcher("&");
+        // System.out.println(m.matches());
+        p = Pattern.compile("[abc[123]&&[345]def]");
+        m = p.matcher("a");
+        // System.out.println(m.matches());
+
+        // icu4c rightly considers a missing rhs to && a syntax error.
+        if (false) {
+            p = Pattern.compile("[[xyz]&&]");
+        }
+
+        p = Pattern.compile("[[abc]&]");
+
+        try {
+            p = Pattern.compile("[[abc]&&");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        p = Pattern.compile("[[abc]\\&&[xyz]]");
+
+        p = Pattern.compile("[[abc]&\\&[xyz]]");
+
+        // Test 3-way intersection
+        p = Pattern.compile("[[a-p]&&[g-z]&&[d-k]]");
+        m = p.matcher("g");
+        assertTrue(m.matches());
+        m = p.matcher("m");
+        assertFalse(m.matches());
+
+        // Test nested intersection
+        p = Pattern.compile("[[[a-p]&&[g-z]]&&[d-k]]");
+        m = p.matcher("g");
+        assertTrue(m.matches());
+        m = p.matcher("m");
+        assertFalse(m.matches());
+
+        // Test character class subtraction with && and ^
+        p = Pattern.compile("[[a-z]&&[^aeiou]][aeiou][[^xyz]&&[a-z]]");
+        m = p.matcher("pop");
+        assertTrue(m.matches());
+        m = p.matcher("tag");
+        assertTrue(m.matches());
+        m = p.matcher("eat");
+        assertFalse(m.matches());
+        m = p.matcher("tax");
+        assertFalse(m.matches());
+        m = p.matcher("zip");
+        assertTrue(m.matches());
+
+        // Test . (DOT), with and without DOTALL
+        // Note: DOT not allowed in character classes
+        p = Pattern.compile(".+/x.z");
+        m = p.matcher("!$/xyz");
+        assertTrue(m.matches());
+        m = p.matcher("%\n\r/x\nz");
+        assertFalse(m.matches());
+        p = Pattern.compile(".+/x.z", Pattern.DOTALL);
+        m = p.matcher("%\n\r/x\nz");
+        assertTrue(m.matches());
+
+        // Test \d (digit)
+        p = Pattern.compile("\\d+[a-z][\\dx]");
+        m = p.matcher("42a6");
+        assertTrue(m.matches());
+        m = p.matcher("21zx");
+        assertTrue(m.matches());
+        m = p.matcher("ab6");
+        assertFalse(m.matches());
+        m = p.matcher("56912f9");
+        assertTrue(m.matches());
+
+        // Test \D (not a digit)
+        p = Pattern.compile("\\D+[a-z]-[\\D3]");
+        m = p.matcher("za-p");
+        assertTrue(m.matches());
+        m = p.matcher("%!e-3");
+        assertTrue(m.matches());
+        m = p.matcher("9a-x");
+        assertFalse(m.matches());
+        m = p.matcher("\u1234pp\ny-3");
+        assertTrue(m.matches());
+
+        // Test \s (whitespace)
+        p = Pattern.compile("<[a-zA-Z]+\\s+[0-9]+[\\sx][^\\s]>");
+        m = p.matcher("<cat \t1\fx>");
+        assertTrue(m.matches());
+        m = p.matcher("<cat \t1\f >");
+        assertFalse(m.matches());
+        m = p
+                .matcher("xyz <foo\n\r22 5> <pp \t\n\f\r \u000b41x\u1234><pp \nx7\rc> zzz");
+        assertTrue(m.find());
+        assertTrue(m.find());
+        assertFalse(m.find());
+
+        // Test \S (not whitespace)
+        p = Pattern.compile("<[a-z] \\S[0-9][\\S\n]+[^\\S]221>");
+        m = p.matcher("<f $0**\n** 221>");
+        assertTrue(m.matches());
+        m = p.matcher("<x 441\t221>");
+        assertTrue(m.matches());
+        m = p.matcher("<z \t9\ng 221>");
+        assertFalse(m.matches());
+        m = p.matcher("<z 60\ngg\u1234\f221>");
+        assertTrue(m.matches());
+        p = Pattern.compile("<[a-z] \\S[0-9][\\S\n]+[^\\S]221[\\S&&[^abc]]>");
+        m = p.matcher("<f $0**\n** 221x>");
+        assertTrue(m.matches());
+        m = p.matcher("<x 441\t221z>");
+        assertTrue(m.matches());
+        m = p.matcher("<x 441\t221 >");
+        assertFalse(m.matches());
+        m = p.matcher("<x 441\t221c>");
+        assertFalse(m.matches());
+        m = p.matcher("<z \t9\ng 221x>");
+        assertFalse(m.matches());
+        m = p.matcher("<z 60\ngg\u1234\f221\u0001>");
+        assertTrue(m.matches());
+
+        // Test \w (ascii word)
+        p = Pattern.compile("<\\w+\\s[0-9]+;[^\\w]\\w+/[\\w$]+;");
+        m = p.matcher("<f1 99;!foo5/a$7;");
+        assertTrue(m.matches());
+        m = p.matcher("<f$ 99;!foo5/a$7;");
+        assertFalse(m.matches());
+        m = p
+                .matcher("<abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 99;!foo5/a$7;");
+        assertTrue(m.matches());
+
+        // Test \W (not an ascii word)
+        p = Pattern.compile("<\\W\\w+\\s[0-9]+;[\\W_][^\\W]+\\s[0-9]+;");
+        m = p.matcher("<$foo3\n99;_bar\t0;");
+        assertTrue(m.matches());
+        m = p.matcher("<hh 99;_g 0;");
+        assertFalse(m.matches());
+        m = p.matcher("<*xx\t00;^zz\f11;");
+        assertTrue(m.matches());
+
+        // Test x|y pattern
+        // TODO
+    }
+
+    public void testPOSIXGroups() throws PatternSyntaxException {
+        Pattern p;
+        Matcher m;
+
+        // Test POSIX groups using \p and \P (in the group and not in the group)
+        // Groups are Lower, Upper, ASCII, Alpha, Digit, XDigit, Alnum, Punct,
+        // Graph, Print, Blank, Space, Cntrl
+        // Test \p{Lower}
+        /*
+         * FIXME: Requires complex range processing p = Pattern.compile("<\\p{Lower}\\d\\P{Lower}:[\\p{Lower}Z]\\s[^\\P{Lower}]>");
+         * m = p.matcher("<a4P:g x>"); assertTrue(m.matches()); m = p.matcher("<p4%:Z\tq>");
+         * assertTrue(m.matches()); m = p.matcher("<A6#:e e>");
+         * assertFalse(m.matches());
+         */
+        p = Pattern.compile("\\p{Lower}+");
+        m = p.matcher("abcdefghijklmnopqrstuvwxyz");
+        assertTrue(m.matches());
+
+        // Invalid uses of \p{Lower}
+        try {
+            p = Pattern.compile("\\p");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\p;");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\p{");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\p{;");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\p{Lower");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\p{Lower;");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        // Test \p{Upper}
+        /*
+         * FIXME: Requires complex range processing p = Pattern.compile("<\\p{Upper}\\d\\P{Upper}:[\\p{Upper}z]\\s[^\\P{Upper}]>");
+         * m = p.matcher("<A4p:G X>"); assertTrue(m.matches()); m = p.matcher("<P4%:z\tQ>");
+         * assertTrue(m.matches()); m = p.matcher("<a6#:E E>");
+         * assertFalse(m.matches());
+         */
+        p = Pattern.compile("\\p{Upper}+");
+        m = p.matcher("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+        assertTrue(m.matches());
+
+        // Invalid uses of \p{Upper}
+        try {
+            p = Pattern.compile("\\p{Upper");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\p{Upper;");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        // Test \p{ASCII}
+        /*
+         * FIXME: Requires complex range processing p = Pattern.compile("<\\p{ASCII}\\d\\P{ASCII}:[\\p{ASCII}\u1234]\\s[^\\P{ASCII}]>");
+         * m = p.matcher("<A4\u0080:G X>"); assertTrue(m.matches()); m =
+         * p.matcher("<P4\u00ff:\u1234\t\n>"); assertTrue(m.matches()); m =
+         * p.matcher("<\u00846#:E E>"); assertFalse(m.matches())
+         */
+        int i;
+        p = Pattern.compile("\\p{ASCII}");
+        for (i = 0; i < 0x80; i++) {
+            m = p.matcher(Character.toString((char) i));
+            assertTrue(m.matches());
+        }
+        for (; i < 0xff; i++) {
+            m = p.matcher(Character.toString((char) i));
+            assertFalse(m.matches());
+        }
+
+        // Invalid uses of \p{ASCII}
+        try {
+            p = Pattern.compile("\\p{ASCII");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        try {
+            p = Pattern.compile("\\p{ASCII;");
+            fail("PatternSyntaxException expected");
+        } catch (PatternSyntaxException e) {
+        }
+
+        // Test \p{Alpha}
+        // TODO
+
+        // Test \p{Digit}
+        // TODO
+
+        // Test \p{XDigit}
+        // TODO
+
+        // Test \p{Alnum}
+        // TODO
+
+        // Test \p{Punct}
+        // TODO
+
+        // Test \p{Graph}
+        // TODO
+
+        // Test \p{Print}
+        // TODO
+
+        // Test \p{Blank}
+        // TODO
+
+        // Test \p{Space}
+        // TODO
+
+        // Test \p{Cntrl}
+        // TODO
+    }
+
+    public void testUnicodeBlocks() throws PatternSyntaxException {
+        Pattern p;
+        Matcher m;
+        int i, j;
+
+        // Test Unicode blocks using \p and \P
+        // FIXME:
+        // Note that LatinExtended-B and ArabicPresentations-B are unrecognized
+        // by the reference JDK.
+        for (i = 0; i < UBlocks.length; i++) {
+            /*
+             * p = Pattern.compile("\\p{"+UBlocks[i].name+"}");
+             * 
+             * if (UBlocks[i].low > 0) { m =
+             * p.matcher(Character.toString((char)(UBlocks[i].low-1)));
+             * assertFalse(m.matches()); } for (j=UBlocks[i].low; j <=
+             * UBlocks[i].high; j++) { m =
+             * p.matcher(Character.toString((char)j)); assertTrue(m.matches()); }
+             * if (UBlocks[i].high < 0xFFFF) { m =
+             * p.matcher(Character.toString((char)(UBlocks[i].high+1)));
+             * assertFalse(m.matches()); }
+             * 
+             * p = Pattern.compile("\\P{"+UBlocks[i].name+"}");
+             * 
+             * if (UBlocks[i].low > 0) { m =
+             * p.matcher(Character.toString((char)(UBlocks[i].low-1)));
+             * assertTrue(m.matches()); } for (j=UBlocks[i].low; j <
+             * UBlocks[i].high; j++) { m =
+             * p.matcher(Character.toString((char)j)); assertFalse(m.matches()); }
+             * if (UBlocks[i].high < 0xFFFF) { m =
+             * p.matcher(Character.toString((char)(UBlocks[i].high+1)));
+             * assertTrue(m.matches()); }
+             */
+
+            p = Pattern.compile("\\p{In" + UBlocks[i].name + "}");
+
+            if (UBlocks[i].low > 0) {
+                m = p.matcher(Character.toString((char) (UBlocks[i].low - 1)));
+                assertFalse(UBlocks[i].name, m.matches());
+            }
+            for (j = UBlocks[i].low; j <= UBlocks[i].high; j++) {
+                m = p.matcher(Character.toString((char) j));
+                assertTrue(UBlocks[i].name, m.matches());
+            }
+            if (UBlocks[i].high < 0xFFFF) {
+                m = p.matcher(Character.toString((char) (UBlocks[i].high + 1)));
+                assertFalse(UBlocks[i].name, m.matches());
+            }
+
+            p = Pattern.compile("\\P{In" + UBlocks[i].name + "}");
+
+            if (UBlocks[i].low > 0) {
+                m = p.matcher(Character.toString((char) (UBlocks[i].low - 1)));
+                assertTrue(UBlocks[i].name, m.matches());
+            }
+            for (j = UBlocks[i].low; j < UBlocks[i].high; j++) {
+                m = p.matcher(Character.toString((char) j));
+                assertFalse(UBlocks[i].name, m.matches());
+            }
+            if (UBlocks[i].high < 0xFFFF) {
+                m = p.matcher(Character.toString((char) (UBlocks[i].high + 1)));
+                assertTrue(UBlocks[i].name, m.matches());
+            }
+        }
+    }
+
+    public void testMisc() throws PatternSyntaxException {
+        Pattern p;
+        Matcher m;
+
+        // Test (?>...)
+        // TODO
+
+        // Test (?onflags-offflags)
+        // Valid flags are i,m,d,s,u,x
+        // TODO
+
+        // Test (?onflags-offflags:...)
+        // TODO
+
+        // Test \Q, \E
+        p = Pattern.compile("[a-z]+;\\Q[a-z]+;\\Q(foo.*);\\E[0-9]+");
+        m = p.matcher("abc;[a-z]+;\\Q(foo.*);411");
+        assertTrue(m.matches());
+        m = p.matcher("abc;def;foo42;555");
+        assertFalse(m.matches());
+        m = p.matcher("abc;\\Qdef;\\Qfoo99;\\E123");
+        assertFalse(m.matches());
+
+        p = Pattern.compile("[a-z]+;(foo[0-9]-\\Q(...)\\E);[0-9]+");
+        m = p.matcher("abc;foo5-(...);123");
+        assertTrue(m.matches());
+        assertEquals("foo5-(...)", m.group(1));
+        m = p.matcher("abc;foo9-(xxx);789");
+        assertFalse(m.matches());
+
+        p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q$-\\E]+);[0-9]+");
+        m = p.matcher("abc;bar0-def$-;123");
+        assertTrue(m.matches());
+
+        // FIXME:
+        // This should work the same as the pattern above but fails with the
+        // the reference JDK
+        p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q-$\\E]+);[0-9]+");
+        m = p.matcher("abc;bar0-def$-;123");
+        // assertTrue(m.matches());
+
+        // FIXME:
+        // This should work too .. it looks as if just about anything that
+        // has more
+        // than one character between \Q and \E is broken in the the reference
+        // JDK
+        p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q[0-9]\\E]+);[0-9]+");
+        m = p.matcher("abc;bar0-def[99]-]0x[;123");
+        // assertTrue(m.matches());
+
+        // This is the same as above but with explicit escapes .. and this
+        // does work
+        // on the the reference JDK
+        p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\[0\\-9\\]]+);[0-9]+");
+        m = p.matcher("abc;bar0-def[99]-]0x[;123");
+        assertTrue(m.matches());
+
+        // Test #<comment text>
+        // TODO
+    }
+
+    public void testCompile1() throws PatternSyntaxException {
+        Pattern pattern = Pattern
+                .compile("[0-9A-Za-z][0-9A-Za-z\\x2e\\x3a\\x2d\\x5f]*");
+        String name = "iso-8859-1";
+        assertTrue(pattern.matcher(name).matches());
+    }
+
+    public void testCompile2() throws PatternSyntaxException {
+        String findString = "\\Qimport\\E";
+
+        Pattern pattern = Pattern.compile(findString, 0);
+        Matcher matcher = pattern.matcher(new String(
+                "import a.A;\n\n import b.B;\nclass C {}"));
+
+        assertTrue(matcher.find(0));
+    }
+
+    public void testCompile3() throws PatternSyntaxException {
+        Pattern p;
+        Matcher m;
+        p = Pattern.compile("a$");
+        m = p.matcher("a\n");
+        assertTrue(m.find());
+        assertEquals("a", m.group());
+        assertFalse(m.find());
+
+        p = Pattern.compile("(a$)");
+        m = p.matcher("a\n");
+        assertTrue(m.find());
+        assertEquals("a", m.group());
+        assertEquals("a", m.group(1));
+        assertFalse(m.find());
+
+        p = Pattern.compile("^.*$", Pattern.MULTILINE);
+
+        m = p.matcher("a\n");
+        assertTrue(m.find());
+        // System.out.println("["+m.group()+"]");
+        assertEquals("a", m.group());
+        assertFalse(m.find());
+
+        m = p.matcher("a\nb\n");
+        assertTrue(m.find());
+        // System.out.println("["+m.group()+"]");
+        assertEquals("a", m.group());
+        assertTrue(m.find());
+        // System.out.println("["+m.group()+"]");
+        assertEquals("b", m.group());
+        assertFalse(m.find());
+
+        m = p.matcher("a\nb");
+        assertTrue(m.find());
+        // System.out.println("["+m.group()+"]");
+        assertEquals("a", m.group());
+        assertTrue(m.find());
+        assertEquals("b", m.group());
+        assertFalse(m.find());
+
+        m = p.matcher("\naa\r\nbb\rcc\n\n");
+        assertTrue(m.find());
+        // System.out.println("["+m.group()+"]");
+        assertTrue(m.group().equals(""));
+        assertTrue(m.find());
+        // System.out.println("["+m.group()+"]");
+        assertEquals("aa", m.group());
+        assertTrue(m.find());
+        // System.out.println("["+m.group()+"]");
+        assertEquals("bb", m.group());
+        assertTrue(m.find());
+        // System.out.println("["+m.group()+"]");
+        assertEquals("cc", m.group());
+        assertTrue(m.find());
+        // System.out.println("["+m.group()+"]");
+        assertTrue(m.group().equals(""));
+        assertFalse(m.find());
+
+        m = p.matcher("a");
+        assertTrue(m.find());
+        assertEquals("a", m.group());
+        assertFalse(m.find());
+
+        m = p.matcher("");
+        // This differs from the RI behaviour but seems more correct.
+        assertTrue(m.find());
+        assertTrue(m.group().equals(""));
+        assertFalse(m.find());
+
+        p = Pattern.compile("^.*$");
+        m = p.matcher("");
+        assertTrue(m.find());
+        assertTrue(m.group().equals(""));
+        assertFalse(m.find());
+    }
+
+    public void testCompile4() throws PatternSyntaxException {
+        String findString = "\\Qpublic\\E";
+        StringBuffer text = new StringBuffer("    public class Class {\n"
+                + "    public class Class {");
+
+        Pattern pattern = Pattern.compile(findString, 0);
+        Matcher matcher = pattern.matcher(text);
+
+        boolean found = matcher.find();
+        assertTrue(found);
+        assertEquals(4, matcher.start());
+        if (found) {
+            // modify text
+            text.delete(0, text.length());
+            text.append("Text have been changed.");
+            matcher.reset(text);
+        }
+
+        found = matcher.find();
+        assertFalse(found);
+    }
+
+    public void testCompile5() throws PatternSyntaxException {
+        Pattern p = Pattern.compile("^[0-9]");
+        String s[] = p.split("12", -1);
+        assertEquals("", s[0]);
+        assertEquals("2", s[1]);
+        assertEquals(2, s.length);
+    }
+
+    // public void testCompile6() {
+    // String regex = "[\\p{L}[\\p{Mn}[\\p{Pc}[\\p{Nd}[\\p{Nl}[\\p{Sc}]]]]]]+";
+    // String regex = "[\\p{L}\\p{Mn}\\p{Pc}\\p{Nd}\\p{Nl}\\p{Sc}]+";
+    // try {
+    // Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
+    // assertTrue(true);
+    // } catch (PatternSyntaxException e) {
+    // System.out.println(e.getMessage());
+    // assertTrue(false);
+    // }
+    // }
+
+    private static class UBInfo {
+        public UBInfo(int low, int high, String name) {
+            this.name = name;
+            this.low = low;
+            this.high = high;
+        }
+
+        public String name;
+
+        public int low, high;
+    }
+
+    // A table representing the unicode categories
+    // private static UBInfo[] UCategories = {
+    // Lu
+    // Ll
+    // Lt
+    // Lm
+    // Lo
+    // Mn
+    // Mc
+    // Me
+    // Nd
+    // Nl
+    // No
+    // Pc
+    // Pd
+    // Ps
+    // Pe
+    // Pi
+    // Pf
+    // Po
+    // Sm
+    // Sc
+    // Sk
+    // So
+    // Zs
+    // Zl
+    // Zp
+    // Cc
+    // Cf
+    // Cs
+    // Co
+    // Cn
+    // };
+
+    // A table representing the unicode character blocks
+    private static UBInfo[] UBlocks = {
+    /* 0000; 007F; Basic Latin */
+    new UBInfo(0x0000, 0x007F, "BasicLatin"), // Character.UnicodeBlock.BASIC_LATIN
+            /* 0080; 00FF; Latin-1 Supplement */
+            new UBInfo(0x0080, 0x00FF, "Latin-1Supplement"), // Character.UnicodeBlock.LATIN_1_SUPPLEMENT
+            /* 0100; 017F; Latin Extended-A */
+            new UBInfo(0x0100, 0x017F, "LatinExtended-A"), // Character.UnicodeBlock.LATIN_EXTENDED_A
+            /* 0180; 024F; Latin Extended-B */
+            // new UBInfo (0x0180,0x024F,"InLatinExtended-B"), //
+            // Character.UnicodeBlock.LATIN_EXTENDED_B
+            /* 0250; 02AF; IPA Extensions */
+            new UBInfo(0x0250, 0x02AF, "IPAExtensions"), // Character.UnicodeBlock.IPA_EXTENSIONS
+            /* 02B0; 02FF; Spacing Modifier Letters */
+            new UBInfo(0x02B0, 0x02FF, "SpacingModifierLetters"), // Character.UnicodeBlock.SPACING_MODIFIER_LETTERS
+            /* 0300; 036F; Combining Diacritical Marks */
+            new UBInfo(0x0300, 0x036F, "CombiningDiacriticalMarks"), // Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS
+            /* 0370; 03FF; Greek */
+            new UBInfo(0x0370, 0x03FF, "Greek"), // Character.UnicodeBlock.GREEK
+            /* 0400; 04FF; Cyrillic */
+            new UBInfo(0x0400, 0x04FF, "Cyrillic"), // Character.UnicodeBlock.CYRILLIC
+            /* 0530; 058F; Armenian */
+            new UBInfo(0x0530, 0x058F, "Armenian"), // Character.UnicodeBlock.ARMENIAN
+            /* 0590; 05FF; Hebrew */
+            new UBInfo(0x0590, 0x05FF, "Hebrew"), // Character.UnicodeBlock.HEBREW
+            /* 0600; 06FF; Arabic */
+            new UBInfo(0x0600, 0x06FF, "Arabic"), // Character.UnicodeBlock.ARABIC
+            /* 0700; 074F; Syriac */
+            new UBInfo(0x0700, 0x074F, "Syriac"), // Character.UnicodeBlock.SYRIAC
+            /* 0780; 07BF; Thaana */
+            new UBInfo(0x0780, 0x07BF, "Thaana"), // Character.UnicodeBlock.THAANA
+            /* 0900; 097F; Devanagari */
+            new UBInfo(0x0900, 0x097F, "Devanagari"), // Character.UnicodeBlock.DEVANAGARI
+            /* 0980; 09FF; Bengali */
+            new UBInfo(0x0980, 0x09FF, "Bengali"), // Character.UnicodeBlock.BENGALI
+            /* 0A00; 0A7F; Gurmukhi */
+            new UBInfo(0x0A00, 0x0A7F, "Gurmukhi"), // Character.UnicodeBlock.GURMUKHI
+            /* 0A80; 0AFF; Gujarati */
+            new UBInfo(0x0A80, 0x0AFF, "Gujarati"), // Character.UnicodeBlock.GUJARATI
+            /* 0B00; 0B7F; Oriya */
+            new UBInfo(0x0B00, 0x0B7F, "Oriya"), // Character.UnicodeBlock.ORIYA
+            /* 0B80; 0BFF; Tamil */
+            new UBInfo(0x0B80, 0x0BFF, "Tamil"), // Character.UnicodeBlock.TAMIL
+            /* 0C00; 0C7F; Telugu */
+            new UBInfo(0x0C00, 0x0C7F, "Telugu"), // Character.UnicodeBlock.TELUGU
+            /* 0C80; 0CFF; Kannada */
+            new UBInfo(0x0C80, 0x0CFF, "Kannada"), // Character.UnicodeBlock.KANNADA
+            /* 0D00; 0D7F; Malayalam */
+            new UBInfo(0x0D00, 0x0D7F, "Malayalam"), // Character.UnicodeBlock.MALAYALAM
+            /* 0D80; 0DFF; Sinhala */
+            new UBInfo(0x0D80, 0x0DFF, "Sinhala"), // Character.UnicodeBlock.SINHALA
+            /* 0E00; 0E7F; Thai */
+            new UBInfo(0x0E00, 0x0E7F, "Thai"), // Character.UnicodeBlock.THAI
+            /* 0E80; 0EFF; Lao */
+            new UBInfo(0x0E80, 0x0EFF, "Lao"), // Character.UnicodeBlock.LAO
+            /* 0F00; 0FFF; Tibetan */
+            new UBInfo(0x0F00, 0x0FFF, "Tibetan"), // Character.UnicodeBlock.TIBETAN
+            /* 1000; 109F; Myanmar */
+            new UBInfo(0x1000, 0x109F, "Myanmar"), // Character.UnicodeBlock.MYANMAR
+            /* 10A0; 10FF; Georgian */
+            new UBInfo(0x10A0, 0x10FF, "Georgian"), // Character.UnicodeBlock.GEORGIAN
+            /* 1100; 11FF; Hangul Jamo */
+            new UBInfo(0x1100, 0x11FF, "HangulJamo"), // Character.UnicodeBlock.HANGUL_JAMO
+            /* 1200; 137F; Ethiopic */
+            new UBInfo(0x1200, 0x137F, "Ethiopic"), // Character.UnicodeBlock.ETHIOPIC
+            /* 13A0; 13FF; Cherokee */
+            new UBInfo(0x13A0, 0x13FF, "Cherokee"), // Character.UnicodeBlock.CHEROKEE
+            /* 1400; 167F; Unified Canadian Aboriginal Syllabics */
+            new UBInfo(0x1400, 0x167F, "UnifiedCanadianAboriginalSyllabics"), // Character.UnicodeBlock.UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS
+            /* 1680; 169F; Ogham */
+            new UBInfo(0x1680, 0x169F, "Ogham"), // Character.UnicodeBlock.OGHAM
+            /* 16A0; 16FF; Runic */
+            new UBInfo(0x16A0, 0x16FF, "Runic"), // Character.UnicodeBlock.RUNIC
+            /* 1780; 17FF; Khmer */
+            new UBInfo(0x1780, 0x17FF, "Khmer"), // Character.UnicodeBlock.KHMER
+            /* 1800; 18AF; Mongolian */
+            new UBInfo(0x1800, 0x18AF, "Mongolian"), // Character.UnicodeBlock.MONGOLIAN
+            /* 1E00; 1EFF; Latin Extended Additional */
+            new UBInfo(0x1E00, 0x1EFF, "LatinExtendedAdditional"), // Character.UnicodeBlock.LATIN_EXTENDED_ADDITIONAL
+            /* 1F00; 1FFF; Greek Extended */
+            new UBInfo(0x1F00, 0x1FFF, "GreekExtended"), // Character.UnicodeBlock.GREEK_EXTENDED
+            /* 2000; 206F; General Punctuation */
+            new UBInfo(0x2000, 0x206F, "GeneralPunctuation"), // Character.UnicodeBlock.GENERAL_PUNCTUATION
+            /* 2070; 209F; Superscripts and Subscripts */
+            new UBInfo(0x2070, 0x209F, "SuperscriptsandSubscripts"), // Character.UnicodeBlock.SUPERSCRIPTS_AND_SUBSCRIPTS
+            /* 20A0; 20CF; Currency Symbols */
+            new UBInfo(0x20A0, 0x20CF, "CurrencySymbols"), // Character.UnicodeBlock.CURRENCY_SYMBOLS
+            /* 20D0; 20FF; Combining Marks for Symbols */
+            new UBInfo(0x20D0, 0x20FF, "CombiningMarksforSymbols"), // Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS
+            /* 2100; 214F; Letterlike Symbols */
+            new UBInfo(0x2100, 0x214F, "LetterlikeSymbols"), // Character.UnicodeBlock.LETTERLIKE_SYMBOLS
+            /* 2150; 218F; Number Forms */
+            new UBInfo(0x2150, 0x218F, "NumberForms"), // Character.UnicodeBlock.NUMBER_FORMS
+            /* 2190; 21FF; Arrows */
+            new UBInfo(0x2190, 0x21FF, "Arrows"), // Character.UnicodeBlock.ARROWS
+            /* 2200; 22FF; Mathematical Operators */
+            new UBInfo(0x2200, 0x22FF, "MathematicalOperators"), // Character.UnicodeBlock.MATHEMATICAL_OPERATORS
+            /* 2300; 23FF; Miscellaneous Technical */
+            new UBInfo(0x2300, 0x23FF, "MiscellaneousTechnical"), // Character.UnicodeBlock.MISCELLANEOUS_TECHNICAL
+            /* 2400; 243F; Control Pictures */
+            new UBInfo(0x2400, 0x243F, "ControlPictures"), // Character.UnicodeBlock.CONTROL_PICTURES
+            /* 2440; 245F; Optical Character Recognition */
+            new UBInfo(0x2440, 0x245F, "OpticalCharacterRecognition"), // Character.UnicodeBlock.OPTICAL_CHARACTER_RECOGNITION
+            /* 2460; 24FF; Enclosed Alphanumerics */
+            new UBInfo(0x2460, 0x24FF, "EnclosedAlphanumerics"), // Character.UnicodeBlock.ENCLOSED_ALPHANUMERICS
+            /* 2500; 257F; Box Drawing */
+            new UBInfo(0x2500, 0x257F, "BoxDrawing"), // Character.UnicodeBlock.BOX_DRAWING
+            /* 2580; 259F; Block Elements */
+            new UBInfo(0x2580, 0x259F, "BlockElements"), // Character.UnicodeBlock.BLOCK_ELEMENTS
+            /* 25A0; 25FF; Geometric Shapes */
+            new UBInfo(0x25A0, 0x25FF, "GeometricShapes"), // Character.UnicodeBlock.GEOMETRIC_SHAPES
+            /* 2600; 26FF; Miscellaneous Symbols */
+            new UBInfo(0x2600, 0x26FF, "MiscellaneousSymbols"), // Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS
+            /* 2700; 27BF; Dingbats */
+            new UBInfo(0x2700, 0x27BF, "Dingbats"), // Character.UnicodeBlock.DINGBATS
+            /* 2800; 28FF; Braille Patterns */
+            new UBInfo(0x2800, 0x28FF, "BraillePatterns"), // Character.UnicodeBlock.BRAILLE_PATTERNS
+            /* 2E80; 2EFF; CJK Radicals Supplement */
+            new UBInfo(0x2E80, 0x2EFF, "CJKRadicalsSupplement"), // Character.UnicodeBlock.CJK_RADICALS_SUPPLEMENT
+            /* 2F00; 2FDF; Kangxi Radicals */
+            new UBInfo(0x2F00, 0x2FDF, "KangxiRadicals"), // Character.UnicodeBlock.KANGXI_RADICALS
+            /* 2FF0; 2FFF; Ideographic Description Characters */
+            new UBInfo(0x2FF0, 0x2FFF, "IdeographicDescriptionCharacters"), // Character.UnicodeBlock.IDEOGRAPHIC_DESCRIPTION_CHARACTERS
+            /* 3000; 303F; CJK Symbols and Punctuation */
+            new UBInfo(0x3000, 0x303F, "CJKSymbolsandPunctuation"), // Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
+            /* 3040; 309F; Hiragana */
+            new UBInfo(0x3040, 0x309F, "Hiragana"), // Character.UnicodeBlock.HIRAGANA
+            /* 30A0; 30FF; Katakana */
+            new UBInfo(0x30A0, 0x30FF, "Katakana"), // Character.UnicodeBlock.KATAKANA
+            /* 3100; 312F; Bopomofo */
+            new UBInfo(0x3100, 0x312F, "Bopomofo"), // Character.UnicodeBlock.BOPOMOFO
+            /* 3130; 318F; Hangul Compatibility Jamo */
+            new UBInfo(0x3130, 0x318F, "HangulCompatibilityJamo"), // Character.UnicodeBlock.HANGUL_COMPATIBILITY_JAMO
+            /* 3190; 319F; Kanbun */
+            new UBInfo(0x3190, 0x319F, "Kanbun"), // Character.UnicodeBlock.KANBUN
+            /* 31A0; 31BF; Bopomofo Extended */
+            new UBInfo(0x31A0, 0x31BF, "BopomofoExtended"), // Character.UnicodeBlock.BOPOMOFO_EXTENDED
+            /* 3200; 32FF; Enclosed CJK Letters and Months */
+            new UBInfo(0x3200, 0x32FF, "EnclosedCJKLettersandMonths"), // Character.UnicodeBlock.ENCLOSED_CJK_LETTERS_AND_MONTHS
+            /* 3300; 33FF; CJK Compatibility */
+            new UBInfo(0x3300, 0x33FF, "CJKCompatibility"), // Character.UnicodeBlock.CJK_COMPATIBILITY
+            /* 3400; 4DB5; CJK Unified Ideographs Extension A */
+            new UBInfo(0x3400, 0x4DBF, "CJKUnifiedIdeographsExtensionA"), // Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
+            /* 4E00; 9FFF; CJK Unified Ideographs */
+            new UBInfo(0x4E00, 0x9FFF, "CJKUnifiedIdeographs"), // Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
+            /* A000; A48F; Yi Syllables */
+            new UBInfo(0xA000, 0xA48F, "YiSyllables"), // Character.UnicodeBlock.YI_SYLLABLES
+            /* A490; A4CF; Yi Radicals */
+            new UBInfo(0xA490, 0xA4CF, "YiRadicals"), // Character.UnicodeBlock.YI_RADICALS
+            /* AC00; D7A3; Hangul Syllables */
+            new UBInfo(0xAC00, 0xD7AF, "HangulSyllables"), // Character.UnicodeBlock.HANGUL_SYLLABLES
+            /* D800; DB7F; High Surrogates */
+            /* DB80; DBFF; High Private Use Surrogates */
+            /* DC00; DFFF; Low Surrogates */
+            /* E000; F8FF; Private Use */
+            /* F900; FAFF; CJK Compatibility Ideographs */
+            new UBInfo(0xF900, 0xFAFF, "CJKCompatibilityIdeographs"), // Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
+            /* FB00; FB4F; Alphabetic Presentation Forms */
+            new UBInfo(0xFB00, 0xFB4F, "AlphabeticPresentationForms"), // Character.UnicodeBlock.ALPHABETIC_PRESENTATION_FORMS
+            /* FB50; FDFF; Arabic Presentation Forms-A */
+            new UBInfo(0xFB50, 0xFDFF, "ArabicPresentationForms-A"), // Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_A
+            /* FE20; FE2F; Combining Half Marks */
+            new UBInfo(0xFE20, 0xFE2F, "CombiningHalfMarks"), // Character.UnicodeBlock.COMBINING_HALF_MARKS
+            /* FE30; FE4F; CJK Compatibility Forms */
+            new UBInfo(0xFE30, 0xFE4F, "CJKCompatibilityForms"), // Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
+            /* FE50; FE6F; Small Form Variants */
+            new UBInfo(0xFE50, 0xFE6F, "SmallFormVariants"), // Character.UnicodeBlock.SMALL_FORM_VARIANTS
+            /* FE70; FEFE; Arabic Presentation Forms-B */
+            new UBInfo(0xFE70, 0xFEFF, "ArabicPresentationForms-B"), // Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_B
+            /* FF00; FFEF; Halfwidth and Fullwidth Forms */
+            new UBInfo(0xFF00, 0xFFEF, "HalfwidthandFullwidthForms"), // Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
+            /* FFF0; FFFD; Specials */
+            new UBInfo(0xFFF0, 0xFFFF, "Specials") // Character.UnicodeBlock.SPECIALS
+    };
+}
diff --git a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternErrorTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/PatternErrorTest.java
similarity index 67%
rename from luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternErrorTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/PatternErrorTest.java
index fd2c3ae..4abb2a0 100644
--- a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternErrorTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/PatternErrorTest.java
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.regex.tests.java.util.regex;
+package org.apache.harmony.tests.java.util.regex;
 
 import java.util.regex.Pattern;
+
 import junit.framework.TestCase;
 
 /**
  * Test boundary and error conditions in java.util.regex.Pattern
- *
  */
+@SuppressWarnings("nls")
 public class PatternErrorTest extends TestCase {
     public void testCompileErrors() throws Exception {
         // null regex string - should get NullPointerException
@@ -32,7 +33,6 @@
         } catch (NullPointerException e) {
         }
 
-
         // empty regex string - no exception should be thrown
         Pattern.compile("");
 
@@ -46,38 +46,22 @@
         flags |= Pattern.UNIX_LINES;
         flags |= Pattern.CASE_INSENSITIVE;
         flags |= Pattern.MULTILINE;
-        // BEGIN android-changed
-        // We don't support that flag.
-        // flags |= Pattern.CANON_EQ;
-        // END android-changed
+        flags |= Pattern.CANON_EQ;
         flags |= Pattern.COMMENTS;
         flags |= Pattern.DOTALL;
         flags |= Pattern.UNICODE_CASE;
+        flags &= ~Pattern.CANON_EQ; // Android always throws given this flag.
         Pattern.compile("foo", flags);
 
         // add invalid flags - should get IllegalArgumentException
-        /*
-         * TODO: Inconsistency between the reference JDK behaviour and spec - exception is
-         * not thrown
-         */
-        /*
-         * Valid test is:
-         * flags |= 0xFFFFFFFF;
-         * try {
-         *   Pattern.compile("foo",flags);
-         * } catch (IllegalArgumentException e) {
-         *   // This is the expected exception
-         * } catch (Exception e) {
-         *   fail();
-         * }
-         */
-
-        /* Workaround test is: */
-        // BEGIN android-changed
-        // We don't support that flag.
-        flags |= ~Pattern.CANON_EQ;
-        // END android-changed
-        // No exception expected to match incorrect the reference behaviour
-        Pattern.compile("foo", flags);
+        // regression test for HARMONY-4248
+        flags |= 0xFFFFFFFF;
+        flags &= ~Pattern.CANON_EQ; // Android always throws given this flag.
+        try {
+            Pattern.compile("foo", flags);
+            fail("Expected IllegalArgumentException to be thrown");
+        } catch (IllegalArgumentException e) {
+            // This is the expected exception
+        }
     }
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ReplaceTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ReplaceTest.java
new file mode 100644
index 0000000..1eac3f3
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ReplaceTest.java
@@ -0,0 +1,90 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.tests.java.util.regex;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("nls")
+public class ReplaceTest extends TestCase {
+
+    public void testSimpleReplace() throws PatternSyntaxException {
+        String target, pattern, repl;
+
+        target = "foobarfobarfoofo1";
+        pattern = "fo[^o]";
+        repl = "xxx";
+
+        Pattern p = Pattern.compile(pattern);
+        Matcher m = p.matcher(target);
+
+        assertEquals("foobarxxxarfoofo1", m.replaceFirst(repl));
+        assertEquals("foobarxxxarfooxxx", m.replaceAll(repl));
+    }
+
+    public void testCaptureReplace() {
+        String target, pattern, repl, s;
+        Pattern p = null;
+        Matcher m;
+
+        target = "[31]foo;bar[42];[99]xyz";
+        pattern = "\\[([0-9]+)\\]([a-z]+)";
+        repl = "$2[$1]";
+
+        p = Pattern.compile(pattern);
+        m = p.matcher(target);
+        s = m.replaceFirst(repl);
+        assertEquals("foo[31];bar[42];[99]xyz", s);
+        s = m.replaceAll(repl);
+        assertEquals("foo[31];bar[42];xyz[99]", s);
+
+        target = "[31]foo(42)bar{63}zoo;[12]abc(34)def{56}ghi;{99}xyz[88]xyz(77)xyz;";
+        pattern = "\\[([0-9]+)\\]([a-z]+)\\(([0-9]+)\\)([a-z]+)\\{([0-9]+)\\}([a-z]+)";
+        repl = "[$5]$6($3)$4{$1}$2";
+        p = Pattern.compile(pattern);
+        m = p.matcher(target);
+        s = m.replaceFirst(repl);
+        // System.out.println(s);
+        assertEquals(
+                "[63]zoo(42)bar{31}foo;[12]abc(34)def{56}ghi;{99}xyz[88]xyz(77)xyz;",
+                s);
+        s = m.replaceAll(repl);
+        // System.out.println(s);
+        assertEquals(
+                "[63]zoo(42)bar{31}foo;[56]ghi(34)def{12}abc;{99}xyz[88]xyz(77)xyz;",
+                s);
+    }
+
+    public void testEscapeReplace() {
+        String target, pattern, repl, s;
+
+        target = "foo'bar''foo";
+        pattern = "'";
+        repl = "\\'";
+        s = target.replaceAll(pattern, repl);
+        assertEquals("foo'bar''foo", s);
+        repl = "\\\\'";
+        s = target.replaceAll(pattern, repl);
+        assertEquals("foo\\'bar\\'\\'foo", s);
+        repl = "\\$3";
+        s = target.replaceAll(pattern, repl);
+        assertEquals("foo$3bar$3$3foo", s);
+    }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/SplitTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/SplitTest.java
new file mode 100644
index 0000000..5a5bc2b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/SplitTest.java
@@ -0,0 +1,171 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.tests.java.util.regex;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import junit.framework.TestCase;
+
+/**
+ * TODO Type description
+ */
+@SuppressWarnings("nls")
+public class SplitTest extends TestCase {
+
+    public void testSimple() {
+        Pattern p = Pattern.compile("/");
+        String[] results = p.split("have/you/done/it/right");
+        String[] expected = new String[] { "have", "you", "done", "it", "right" };
+        assertEquals(expected.length, results.length);
+        for (int i = 0; i < expected.length; i++) {
+            assertEquals(results[i], expected[i]);
+        }
+    }
+
+    public void testSplit1() throws PatternSyntaxException {
+        Pattern p = Pattern.compile(" ");
+
+        String input = "poodle zoo";
+        String tokens[];
+
+        tokens = p.split(input, 1);
+        assertEquals(1, tokens.length);
+        assertTrue(tokens[0].equals(input));
+        tokens = p.split(input, 2);
+        assertEquals(2, tokens.length);
+        assertEquals("poodle", tokens[0]);
+        assertEquals("zoo", tokens[1]);
+        tokens = p.split(input, 5);
+        assertEquals(2, tokens.length);
+        assertEquals("poodle", tokens[0]);
+        assertEquals("zoo", tokens[1]);
+        tokens = p.split(input, -2);
+        assertEquals(2, tokens.length);
+        assertEquals("poodle", tokens[0]);
+        assertEquals("zoo", tokens[1]);
+        tokens = p.split(input, 0);
+        assertEquals(2, tokens.length);
+        assertEquals("poodle", tokens[0]);
+        assertEquals("zoo", tokens[1]);
+        tokens = p.split(input);
+        assertEquals(2, tokens.length);
+        assertEquals("poodle", tokens[0]);
+        assertEquals("zoo", tokens[1]);
+
+        p = Pattern.compile("d");
+
+        tokens = p.split(input, 1);
+        assertEquals(1, tokens.length);
+        assertTrue(tokens[0].equals(input));
+        tokens = p.split(input, 2);
+        assertEquals(2, tokens.length);
+        assertEquals("poo", tokens[0]);
+        assertEquals("le zoo", tokens[1]);
+        tokens = p.split(input, 5);
+        assertEquals(2, tokens.length);
+        assertEquals("poo", tokens[0]);
+        assertEquals("le zoo", tokens[1]);
+        tokens = p.split(input, -2);
+        assertEquals(2, tokens.length);
+        assertEquals("poo", tokens[0]);
+        assertEquals("le zoo", tokens[1]);
+        tokens = p.split(input, 0);
+        assertEquals(2, tokens.length);
+        assertEquals("poo", tokens[0]);
+        assertEquals("le zoo", tokens[1]);
+        tokens = p.split(input);
+        assertEquals(2, tokens.length);
+        assertEquals("poo", tokens[0]);
+        assertEquals("le zoo", tokens[1]);
+
+        p = Pattern.compile("o");
+
+        tokens = p.split(input, 1);
+        assertEquals(1, tokens.length);
+        assertTrue(tokens[0].equals(input));
+        tokens = p.split(input, 2);
+        assertEquals(2, tokens.length);
+        assertEquals("p", tokens[0]);
+        assertEquals("odle zoo", tokens[1]);
+        tokens = p.split(input, 5);
+        assertEquals(5, tokens.length);
+        assertEquals("p", tokens[0]);
+        assertTrue(tokens[1].equals(""));
+        assertEquals("dle z", tokens[2]);
+        assertTrue(tokens[3].equals(""));
+        assertTrue(tokens[4].equals(""));
+        tokens = p.split(input, -2);
+        assertEquals(5, tokens.length);
+        assertEquals("p", tokens[0]);
+        assertTrue(tokens[1].equals(""));
+        assertEquals("dle z", tokens[2]);
+        assertTrue(tokens[3].equals(""));
+        assertTrue(tokens[4].equals(""));
+        tokens = p.split(input, 0);
+        assertEquals(3, tokens.length);
+        assertEquals("p", tokens[0]);
+        assertTrue(tokens[1].equals(""));
+        assertEquals("dle z", tokens[2]);
+        tokens = p.split(input);
+        assertEquals(3, tokens.length);
+        assertEquals("p", tokens[0]);
+        assertTrue(tokens[1].equals(""));
+        assertEquals("dle z", tokens[2]);
+    }
+
+    public void testSplit2() {
+        Pattern p = Pattern.compile("");
+        String s[];
+        s = p.split("a", -1);
+        assertEquals(3, s.length);
+        assertEquals("", s[0]);
+        assertEquals("a", s[1]);
+        assertEquals("", s[2]);
+
+        s = p.split("", -1);
+        assertEquals(1, s.length);
+        assertEquals("", s[0]);
+
+        s = p.split("abcd", -1);
+        assertEquals(6, s.length);
+        assertEquals("", s[0]);
+        assertEquals("a", s[1]);
+        assertEquals("b", s[2]);
+        assertEquals("c", s[3]);
+        assertEquals("d", s[4]);
+        assertEquals("", s[5]);
+    }
+
+    public void testSplitSupplementaryWithEmptyString() {
+
+        /*
+         * See http://www.unicode.org/reports/tr18/#Supplementary_Characters We
+         * have to treat text as code points not code units.
+         */
+        Pattern p = Pattern.compile("");
+        String s[];
+        s = p.split("a\ud869\uded6b", -1);
+        assertEquals(5, s.length);
+        assertEquals("", s[0]);
+        assertEquals("a", s[1]);
+        assertEquals("\ud869\uded6", s[2]);
+        assertEquals("b", s[3]);
+        assertEquals("", s[4]);
+    }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/math/BigDecimalTest.java b/harmony-tests/src/test/java/tests/api/java/math/BigDecimalTest.java
new file mode 100644
index 0000000..4fd27bf
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/math/BigDecimalTest.java
@@ -0,0 +1,952 @@
+/*
+ *  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 tests.api.java.math;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+
+public class BigDecimalTest extends junit.framework.TestCase {
+	BigInteger value = new BigInteger("12345908");
+
+	BigInteger value2 = new BigInteger("12334560000");
+
+	/**
+	 * @tests java.math.BigDecimal#BigDecimal(java.math.BigInteger)
+	 */
+	public void test_ConstructorLjava_math_BigInteger() {
+		BigDecimal big = new BigDecimal(value);
+		assertTrue("the BigDecimal value is not initialized properly", big
+				.unscaledValue().equals(value)
+				&& big.scale() == 0);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#BigDecimal(java.math.BigInteger, int)
+	 */
+	public void test_ConstructorLjava_math_BigIntegerI() {
+		BigDecimal big = new BigDecimal(value2, 5);
+		assertTrue("the BigDecimal value is not initialized properly", big
+				.unscaledValue().equals(value2)
+				&& big.scale() == 5);
+		assertTrue("the BigDecimal value is not represented properly", big
+				.toString().equals("123345.60000"));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#BigDecimal(double)
+	 */
+	public void test_ConstructorD() {
+		BigDecimal big = new BigDecimal(123E04);
+		assertTrue(
+				"the BigDecimal value taking a double argument is not initialized properly",
+				big.toString().equals("1230000"));
+		big = new BigDecimal(1.2345E-12);
+		assertTrue("the double representation is not correct", big
+				.doubleValue() == 1.2345E-12);
+		big = new BigDecimal(-12345E-3);
+		assertTrue("the double representation is not correct", big
+				.doubleValue() == -12.345);
+		big = new BigDecimal(5.1234567897654321e138);
+		assertTrue("the double representation is not correct", big
+				.doubleValue() == 5.1234567897654321E138
+				&& big.scale() == 0);
+		big = new BigDecimal(0.1);
+		assertTrue(
+				"the double representation of 0.1 bigDecimal is not correct",
+				big.doubleValue() == 0.1);
+		big = new BigDecimal(0.00345);
+		assertTrue(
+				"the double representation of 0.00345 bigDecimal is not correct",
+				big.doubleValue() == 0.00345);
+        // regression test for HARMONY-2429
+        big = new BigDecimal(-0.0);
+        assertTrue(
+        		"the double representation of -0.0 bigDecimal is not correct",
+        		big.scale() == 0);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#BigDecimal(java.lang.String)
+	 */
+	public void test_ConstructorLjava_lang_String() throws NumberFormatException {
+		BigDecimal big = new BigDecimal("345.23499600293850");
+		assertTrue("the BigDecimal value is not initialized properly", big
+				.toString().equals("345.23499600293850")
+				&& big.scale() == 14);
+		big = new BigDecimal("-12345");
+		assertTrue("the BigDecimal value is not initialized properly", big
+				.toString().equals("-12345")
+				&& big.scale() == 0);
+		big = new BigDecimal("123.");
+		assertTrue("the BigDecimal value is not initialized properly", big
+				.toString().equals("123")
+				&& big.scale() == 0);
+
+		new BigDecimal("1.234E02");
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#BigDecimal(java.lang.String)
+	 */
+	public void test_constructor_String_plus_exp() {
+		/*
+		 * BigDecimal does not support a + sign in the exponent when converting
+		 * from a String
+		 */
+		new BigDecimal(+23e-0);
+		new BigDecimal(-23e+0);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#BigDecimal(java.lang.String)
+	 */
+	public void test_constructor_String_empty() {
+		try {
+			new BigDecimal("");			
+            fail("NumberFormatException expected");
+		} catch (NumberFormatException e) {
+		}
+	}
+	
+	/**
+	 * @tests java.math.BigDecimal#BigDecimal(java.lang.String)
+	 */
+	public void test_constructor_String_plus_minus_exp() {
+		try {
+			new BigDecimal("+35e+-2");			
+            fail("NumberFormatException expected");
+		} catch (NumberFormatException e) {
+		}
+		
+		try {
+			new BigDecimal("-35e-+2");			
+            fail("NumberFormatException expected");
+		} catch (NumberFormatException e) {
+		}
+	}
+    
+    /**
+     * @tests java.math.BigDecimal#BigDecimal(char[])
+     */
+    public void test_constructor_CC_plus_minus_exp() {
+        try {
+            new BigDecimal("+35e+-2".toCharArray());          
+            fail("NumberFormatException expected");
+        } catch (NumberFormatException e) {
+        }
+        
+        try {
+            new BigDecimal("-35e-+2".toCharArray());          
+            fail("NumberFormatException expected");
+        } catch (NumberFormatException e) {
+        }
+    }
+
+	/**
+	 * @tests java.math.BigDecimal#abs()
+	 */
+	public void test_abs() {
+		BigDecimal big = new BigDecimal("-1234");
+		BigDecimal bigabs = big.abs();
+		assertTrue("the absolute value of -1234 is not 1234", bigabs.toString()
+				.equals("1234"));
+		big = new BigDecimal(new BigInteger("2345"), 2);
+		bigabs = big.abs();
+		assertTrue("the absolute value of 23.45 is not 23.45", bigabs
+				.toString().equals("23.45"));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#add(java.math.BigDecimal)
+	 */
+	public void test_addLjava_math_BigDecimal() {
+		BigDecimal add1 = new BigDecimal("23.456");
+		BigDecimal add2 = new BigDecimal("3849.235");
+		BigDecimal sum = add1.add(add2);
+		assertTrue("the sum of 23.456 + 3849.235 is wrong", sum.unscaledValue()
+				.toString().equals("3872691")
+				&& sum.scale() == 3);
+		assertTrue("the sum of 23.456 + 3849.235 is not printed correctly", sum
+				.toString().equals("3872.691"));
+		BigDecimal add3 = new BigDecimal(12.34E02D);
+		assertTrue("the sum of 23.456 + 12.34E02 is not printed correctly",
+				(add1.add(add3)).toString().equals("1257.456"));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#compareTo(java.math.BigDecimal)
+	 */
+	public void test_compareToLjava_math_BigDecimal() {
+		BigDecimal comp1 = new BigDecimal("1.00");
+		BigDecimal comp2 = new BigDecimal(1.000000D);
+		assertTrue("1.00 and 1.000000 should be equal",
+				comp1.compareTo(comp2) == 0);
+		BigDecimal comp3 = new BigDecimal("1.02");
+		assertTrue("1.02 should be bigger than 1.00",
+				comp3.compareTo(comp1) == 1);
+		BigDecimal comp4 = new BigDecimal(0.98D);
+		assertTrue("0.98 should be less than 1.00",
+				comp4.compareTo(comp1) == -1);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#divide(java.math.BigDecimal, int)
+	 */
+	public void test_divideLjava_math_BigDecimalI() {
+		BigDecimal divd1 = new BigDecimal(value, 2);
+		BigDecimal divd2 = new BigDecimal("2.335");
+		BigDecimal divd3 = divd1.divide(divd2, BigDecimal.ROUND_UP);
+		assertTrue("123459.08/2.335 is not correct", divd3.toString().equals(
+				"52873.27")
+				&& divd3.scale() == divd1.scale());
+		assertTrue(
+				"the unscaledValue representation of 123459.08/2.335 is not correct",
+				divd3.unscaledValue().toString().equals("5287327"));
+		divd2 = new BigDecimal(123.4D);
+		divd3 = divd1.divide(divd2, BigDecimal.ROUND_DOWN);
+		assertTrue("123459.08/123.4  is not correct", divd3.toString().equals(
+				"1000.47")
+				&& divd3.scale() == 2);
+		divd2 = new BigDecimal(000D);
+
+		try {
+			divd1.divide(divd2, BigDecimal.ROUND_DOWN);
+            fail("divide by zero is not caught");
+		} catch (ArithmeticException e) {
+		}
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#divide(java.math.BigDecimal, int, int)
+	 */
+	public void test_divideLjava_math_BigDecimalII() {
+		BigDecimal divd1 = new BigDecimal(value2, 4);
+		BigDecimal divd2 = new BigDecimal("0.0023");
+		BigDecimal divd3 = divd1.divide(divd2, 3, BigDecimal.ROUND_HALF_UP);
+		assertTrue("1233456/0.0023 is not correct", divd3.toString().equals(
+				"536285217.391")
+				&& divd3.scale() == 3);
+		divd2 = new BigDecimal(1345.5E-02D);
+		divd3 = divd1.divide(divd2, 0, BigDecimal.ROUND_DOWN);
+		assertTrue(
+				"1233456/13.455 is not correct or does not have the correct scale",
+				divd3.toString().equals("91672") && divd3.scale() == 0);
+		divd2 = new BigDecimal(0000D);
+
+		try {
+			divd1.divide(divd2, 4, BigDecimal.ROUND_DOWN);
+            fail("divide by zero is not caught");
+		} catch (ArithmeticException e) {
+		}
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#doubleValue()
+	 */
+	public void test_doubleValue() {
+		BigDecimal bigDB = new BigDecimal(-1.234E-112);
+//		Commenting out this part because it causes an endless loop (see HARMONY-319 and HARMONY-329)
+//		assertTrue(
+//				"the double representation of this BigDecimal is not correct",
+//				bigDB.doubleValue() == -1.234E-112);
+		bigDB = new BigDecimal(5.00E-324);
+		assertTrue("the double representation of bigDecimal is not correct",
+				bigDB.doubleValue() == 5.00E-324);
+		bigDB = new BigDecimal(1.79E308);
+		assertTrue("the double representation of bigDecimal is not correct",
+				bigDB.doubleValue() == 1.79E308 && bigDB.scale() == 0);
+		bigDB = new BigDecimal(-2.33E102);
+		assertTrue(
+				"the double representation of bigDecimal -2.33E102 is not correct",
+				bigDB.doubleValue() == -2.33E102 && bigDB.scale() == 0);
+		bigDB = new BigDecimal(Double.MAX_VALUE);
+		bigDB = bigDB.add(bigDB);
+		assertTrue(
+				"a  + number out of the double range should return infinity",
+				bigDB.doubleValue() == Double.POSITIVE_INFINITY);
+		bigDB = new BigDecimal(-Double.MAX_VALUE);
+		bigDB = bigDB.add(bigDB);
+		assertTrue(
+				"a  - number out of the double range should return neg infinity",
+				bigDB.doubleValue() == Double.NEGATIVE_INFINITY);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#equals(java.lang.Object)
+	 */
+	public void test_equalsLjava_lang_Object() {
+		BigDecimal equal1 = new BigDecimal(1.00D);
+		BigDecimal equal2 = new BigDecimal("1.0");
+		assertFalse("1.00 and 1.0 should not be equal",
+				equal1.equals(equal2));
+		equal2 = new BigDecimal(1.01D);
+		assertFalse("1.00 and 1.01 should not be equal",
+				equal1.equals(equal2));
+		equal2 = new BigDecimal("1.00");
+		assertFalse("1.00D and 1.00 should not be equal",
+				equal1.equals(equal2));
+		BigInteger val = new BigInteger("100");
+		equal1 = new BigDecimal("1.00");
+		equal2 = new BigDecimal(val, 2);
+		assertTrue("1.00(string) and 1.00(bigInteger) should be equal", equal1
+				.equals(equal2));
+		equal1 = new BigDecimal(100D);
+		equal2 = new BigDecimal("2.34576");
+		assertFalse("100D and 2.34576 should not be equal", equal1
+				.equals(equal2));
+		assertFalse("bigDecimal 100D does not equal string 23415", equal1
+				.equals("23415"));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#floatValue()
+	 */
+	public void test_floatValue() {
+		BigDecimal fl1 = new BigDecimal("234563782344567");
+		assertTrue("the float representation of bigDecimal 234563782344567",
+				fl1.floatValue() == 234563782344567f);
+		BigDecimal fl2 = new BigDecimal(2.345E37);
+		assertTrue("the float representation of bigDecimal 2.345E37", fl2
+				.floatValue() == 2.345E37F);
+		fl2 = new BigDecimal(-1.00E-44);
+		assertTrue("the float representation of bigDecimal -1.00E-44", fl2
+				.floatValue() == -1.00E-44F);
+		fl2 = new BigDecimal(-3E12);
+		assertTrue("the float representation of bigDecimal -3E12", fl2
+				.floatValue() == -3E12F);
+		fl2 = new BigDecimal(Double.MAX_VALUE);
+		assertTrue(
+				"A number can't be represented by float should return infinity",
+				fl2.floatValue() == Float.POSITIVE_INFINITY);
+		fl2 = new BigDecimal(-Double.MAX_VALUE);
+		assertTrue(
+				"A number can't be represented by float should return infinity",
+				fl2.floatValue() == Float.NEGATIVE_INFINITY);
+
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#hashCode()
+	 */
+	public void test_hashCode() {
+		// anything that is equal must have the same hashCode
+		BigDecimal hash = new BigDecimal("1.00");
+		BigDecimal hash2 = new BigDecimal(1.00D);
+		assertTrue("the hashCode of 1.00 and 1.00D is equal",
+				hash.hashCode() != hash2.hashCode() && !hash.equals(hash2));
+		hash2 = new BigDecimal("1.0");
+		assertTrue("the hashCode of 1.0 and 1.00 is equal",
+				hash.hashCode() != hash2.hashCode() && !hash.equals(hash2));
+		BigInteger val = new BigInteger("100");
+		hash2 = new BigDecimal(val, 2);
+		assertTrue("hashCode of 1.00 and 1.00(bigInteger) is not equal", hash
+				.hashCode() == hash2.hashCode()
+				&& hash.equals(hash2));
+		hash = new BigDecimal(value, 2);
+		hash2 = new BigDecimal("-1233456.0000");
+		assertTrue("hashCode of 123459.08 and -1233456.0000 is not equal", hash
+				.hashCode() != hash2.hashCode()
+				&& !hash.equals(hash2));
+		hash2 = new BigDecimal(value.negate(), 2);
+		assertTrue("hashCode of 123459.08 and -123459.08 is not equal", hash
+				.hashCode() != hash2.hashCode()
+				&& !hash.equals(hash2));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#intValue()
+	 */
+	public void test_intValue() {
+		BigDecimal int1 = new BigDecimal(value, 3);
+		assertTrue("the int value of 12345.908 is not 12345",
+				int1.intValue() == 12345);
+		int1 = new BigDecimal("1.99");
+		assertTrue("the int value of 1.99 is not 1", int1.intValue() == 1);
+		int1 = new BigDecimal("23423419083091823091283933");
+		// ran JDK and found representation for the above was -249268259
+		assertTrue("the int value of 23423419083091823091283933 is wrong", int1
+				.intValue() == -249268259);
+		int1 = new BigDecimal(-1235D);
+		assertTrue("the int value of -1235 is not -1235",
+				int1.intValue() == -1235);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#longValue()
+	 */
+	public void test_longValue() {
+		BigDecimal long1 = new BigDecimal(value2.negate(), 0);
+		assertTrue("the long value of 12334560000 is not 12334560000", long1
+				.longValue() == -12334560000L);
+		long1 = new BigDecimal(-1345.348E-123D);
+		assertTrue("the long value of -1345.348E-123D is not zero", long1
+				.longValue() == 0);
+		long1 = new BigDecimal("31323423423419083091823091283933");
+		// ran JDK and found representation for the above was
+		// -5251313250005125155
+		assertTrue(
+				"the long value of 31323423423419083091823091283933 is wrong",
+				long1.longValue() == -5251313250005125155L);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#max(java.math.BigDecimal)
+	 */
+	public void test_maxLjava_math_BigDecimal() {
+		BigDecimal max1 = new BigDecimal(value2, 1);
+		BigDecimal max2 = new BigDecimal(value2, 4);
+		assertTrue("1233456000.0 is not greater than 1233456", max1.max(max2)
+				.equals(max1));
+		max1 = new BigDecimal(-1.224D);
+		max2 = new BigDecimal(-1.2245D);
+		assertTrue("-1.224 is not greater than -1.2245", max1.max(max2).equals(
+				max1));
+		max1 = new BigDecimal(123E18);
+		max2 = new BigDecimal(123E19);
+		assertTrue("123E19 is the not the max", max1.max(max2).equals(max2));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#min(java.math.BigDecimal)
+	 */
+	public void test_minLjava_math_BigDecimal() {
+		BigDecimal min1 = new BigDecimal(-12345.4D);
+		BigDecimal min2 = new BigDecimal(-12345.39D);
+		assertTrue("-12345.39 should have been returned", min1.min(min2)
+				.equals(min1));
+		min1 = new BigDecimal(value2, 5);
+		min2 = new BigDecimal(value2, 0);
+		assertTrue("123345.6 should have been returned", min1.min(min2).equals(
+				min1));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#movePointLeft(int)
+	 */
+	public void test_movePointLeftI() {
+		BigDecimal movePtLeft = new BigDecimal("123456265.34");
+		BigDecimal alreadyMoved = movePtLeft.movePointLeft(5);
+		assertTrue("move point left 5 failed", alreadyMoved.scale() == 7
+				&& alreadyMoved.toString().equals("1234.5626534"));
+		movePtLeft = new BigDecimal(value2.negate(), 0);
+		alreadyMoved = movePtLeft.movePointLeft(12);
+		assertTrue("move point left 12 failed", alreadyMoved.scale() == 12
+				&& alreadyMoved.toString().equals("-0.012334560000"));
+		movePtLeft = new BigDecimal(123E18);
+		alreadyMoved = movePtLeft.movePointLeft(2);
+		assertTrue("move point left 2 failed",
+				alreadyMoved.scale() == movePtLeft.scale() + 2
+						&& alreadyMoved.doubleValue() == 1.23E18);
+		movePtLeft = new BigDecimal(1.123E-12);
+		alreadyMoved = movePtLeft.movePointLeft(3);
+		assertTrue("move point left 3 failed",
+				alreadyMoved.scale() == movePtLeft.scale() + 3
+						&& alreadyMoved.doubleValue() == 1.123E-15);
+		movePtLeft = new BigDecimal(value, 2);
+		alreadyMoved = movePtLeft.movePointLeft(-2);
+		assertTrue("move point left -2 failed",
+				alreadyMoved.scale() == movePtLeft.scale() - 2
+						&& alreadyMoved.toString().equals("12345908"));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#movePointRight(int)
+	 */
+	public void test_movePointRightI() {
+		BigDecimal movePtRight = new BigDecimal("-1.58796521458");
+		BigDecimal alreadyMoved = movePtRight.movePointRight(8);
+		assertTrue("move point right 8 failed", alreadyMoved.scale() == 3
+				&& alreadyMoved.toString().equals("-158796521.458"));
+		movePtRight = new BigDecimal(value, 2);
+		alreadyMoved = movePtRight.movePointRight(4);
+		assertTrue("move point right 4 failed", alreadyMoved.scale() == 0
+				&& alreadyMoved.toString().equals("1234590800"));
+		movePtRight = new BigDecimal(134E12);
+		alreadyMoved = movePtRight.movePointRight(2);
+		assertTrue("move point right 2 failed", alreadyMoved.scale() == 0
+				&& alreadyMoved.toString().equals("13400000000000000"));
+		movePtRight = new BigDecimal(-3.4E-10);
+		alreadyMoved = movePtRight.movePointRight(5);
+		assertTrue("move point right 5 failed",
+				alreadyMoved.scale() == movePtRight.scale() - 5
+						&& alreadyMoved.doubleValue() == -0.000034);
+		alreadyMoved = alreadyMoved.movePointRight(-5);
+		assertTrue("move point right -5 failed", alreadyMoved
+				.equals(movePtRight));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#multiply(java.math.BigDecimal)
+	 */
+	public void test_multiplyLjava_math_BigDecimal() {
+		BigDecimal multi1 = new BigDecimal(value, 5);
+		BigDecimal multi2 = new BigDecimal(2.345D);
+		BigDecimal result = multi1.multiply(multi2);
+		assertTrue("123.45908 * 2.345 is not correct: " + result, result
+				.toString().startsWith("289.51154260")
+				&& result.scale() == multi1.scale() + multi2.scale());
+		multi1 = new BigDecimal("34656");
+		multi2 = new BigDecimal("-2");
+		result = multi1.multiply(multi2);
+		assertTrue("34656 * 2 is not correct", result.toString().equals(
+				"-69312")
+				&& result.scale() == 0);
+		multi1 = new BigDecimal(-2.345E-02);
+		multi2 = new BigDecimal(-134E130);
+		result = multi1.multiply(multi2);
+		assertTrue("-2.345E-02 * -134E130 is not correct " + result.doubleValue(),
+				result.doubleValue() == 3.1422999999999997E130
+						&& result.scale() == multi1.scale() + multi2.scale());
+		multi1 = new BigDecimal("11235");
+		multi2 = new BigDecimal("0");
+		result = multi1.multiply(multi2);
+		assertTrue("11235 * 0 is not correct", result.doubleValue() == 0
+				&& result.scale() == 0);
+		multi1 = new BigDecimal("-0.00234");
+		multi2 = new BigDecimal(13.4E10);
+		result = multi1.multiply(multi2);
+		assertTrue("-0.00234 * 13.4E10 is not correct",
+				result.doubleValue() == -313560000
+						&& result.scale() == multi1.scale() + multi2.scale());
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#negate()
+	 */
+	public void test_negate() {
+		BigDecimal negate1 = new BigDecimal(value2, 7);
+		assertTrue("the negate of 1233.4560000 is not -1233.4560000", negate1
+				.negate().toString().equals("-1233.4560000"));
+		negate1 = new BigDecimal("-23465839");
+		assertTrue("the negate of -23465839 is not 23465839", negate1.negate()
+				.toString().equals("23465839"));
+		negate1 = new BigDecimal(-3.456E6);
+		assertTrue("the negate of -3.456E6 is not 3.456E6", negate1.negate()
+				.negate().equals(negate1));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#scale()
+	 */
+	public void test_scale() {
+		BigDecimal scale1 = new BigDecimal(value2, 8);
+		assertTrue("the scale of the number 123.34560000 is wrong", scale1
+				.scale() == 8);
+		BigDecimal scale2 = new BigDecimal("29389.");
+		assertTrue("the scale of the number 29389. is wrong",
+				scale2.scale() == 0);
+		BigDecimal scale3 = new BigDecimal(3.374E13);
+		assertTrue("the scale of the number 3.374E13 is wrong",
+				scale3.scale() == 0);
+		BigDecimal scale4 = new BigDecimal("-3.45E-203");
+		// note the scale is calculated as 15 digits of 345000.... + exponent -
+		// 1. -1 for the 3
+		assertTrue("the scale of the number -3.45E-203 is wrong: "
+				+ scale4.scale(), scale4.scale() == 205);
+		scale4 = new BigDecimal("-345.4E-200");
+		assertTrue("the scale of the number -345.4E-200 is wrong", scale4
+				.scale() == 201);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#setScale(int)
+	 */
+	public void test_setScaleI() {
+		// rounding mode defaults to zero
+		BigDecimal setScale1 = new BigDecimal(value, 3);
+		BigDecimal setScale2 = setScale1.setScale(5);
+		BigInteger setresult = new BigInteger("1234590800");
+		assertTrue("the number 12345.908 after setting scale is wrong",
+				setScale2.unscaledValue().equals(setresult)
+						&& setScale2.scale() == 5);
+
+		try {
+			setScale2 = setScale1.setScale(2, BigDecimal.ROUND_UNNECESSARY);
+            fail("arithmetic Exception not caught as a result of loosing precision");
+		} catch (ArithmeticException e) {
+		}
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#setScale(int, int)
+	 */
+	public void test_setScaleII() {
+		BigDecimal setScale1 = new BigDecimal(2.323E102);
+		BigDecimal setScale2 = setScale1.setScale(4);
+		assertTrue("the number 2.323E102 after setting scale is wrong",
+				setScale2.scale() == 4);
+		assertTrue("the representation of the number 2.323E102 is wrong",
+				setScale2.doubleValue() == 2.323E102);
+		setScale1 = new BigDecimal("-1.253E-12");
+		setScale2 = setScale1.setScale(17, BigDecimal.ROUND_CEILING);
+		assertTrue("the number -1.253E-12 after setting scale is wrong",
+				setScale2.scale() == 17);
+		assertTrue(
+				"the representation of the number -1.253E-12 after setting scale is wrong, " + setScale2.toString(),
+				setScale2.toString().equals("-1.25300E-12"));
+
+		// testing rounding Mode ROUND_CEILING
+		setScale1 = new BigDecimal(value, 4);
+		setScale2 = setScale1.setScale(1, BigDecimal.ROUND_CEILING);
+		assertTrue(
+				"the number 1234.5908 after setting scale to 1/ROUND_CEILING is wrong",
+				setScale2.toString().equals("1234.6") && setScale2.scale() == 1);
+		BigDecimal setNeg = new BigDecimal(value.negate(), 4);
+		setScale2 = setNeg.setScale(1, BigDecimal.ROUND_CEILING);
+		assertTrue(
+				"the number -1234.5908 after setting scale to 1/ROUND_CEILING is wrong",
+				setScale2.toString().equals("-1234.5")
+						&& setScale2.scale() == 1);
+
+		// testing rounding Mode ROUND_DOWN
+		setScale2 = setNeg.setScale(1, BigDecimal.ROUND_DOWN);
+		assertTrue(
+				"the number -1234.5908 after setting scale to 1/ROUND_DOWN is wrong",
+				setScale2.toString().equals("-1234.5")
+						&& setScale2.scale() == 1);
+		setScale1 = new BigDecimal(value, 4);
+		setScale2 = setScale1.setScale(1, BigDecimal.ROUND_DOWN);
+		assertTrue(
+				"the number 1234.5908 after setting scale to 1/ROUND_DOWN is wrong",
+				setScale2.toString().equals("1234.5") && setScale2.scale() == 1);
+
+		// testing rounding Mode ROUND_FLOOR
+		setScale2 = setScale1.setScale(1, BigDecimal.ROUND_FLOOR);
+		assertTrue(
+				"the number 1234.5908 after setting scale to 1/ROUND_FLOOR is wrong",
+				setScale2.toString().equals("1234.5") && setScale2.scale() == 1);
+		setScale2 = setNeg.setScale(1, BigDecimal.ROUND_FLOOR);
+		assertTrue(
+				"the number -1234.5908 after setting scale to 1/ROUND_FLOOR is wrong",
+				setScale2.toString().equals("-1234.6")
+						&& setScale2.scale() == 1);
+
+		// testing rounding Mode ROUND_HALF_DOWN
+		setScale2 = setScale1.setScale(3, BigDecimal.ROUND_HALF_DOWN);
+		assertTrue(
+				"the number 1234.5908 after setting scale to 3/ROUND_HALF_DOWN is wrong",
+				setScale2.toString().equals("1234.591")
+						&& setScale2.scale() == 3);
+		setScale1 = new BigDecimal(new BigInteger("12345000"), 5);
+		setScale2 = setScale1.setScale(1, BigDecimal.ROUND_HALF_DOWN);
+		assertTrue(
+				"the number 123.45908 after setting scale to 1/ROUND_HALF_DOWN is wrong",
+				setScale2.toString().equals("123.4") && setScale2.scale() == 1);
+		setScale2 = new BigDecimal("-1234.5000").setScale(0,
+				BigDecimal.ROUND_HALF_DOWN);
+		assertTrue(
+				"the number -1234.5908 after setting scale to 0/ROUND_HALF_DOWN is wrong",
+				setScale2.toString().equals("-1234") && setScale2.scale() == 0);
+
+		// testing rounding Mode ROUND_HALF_EVEN
+		setScale1 = new BigDecimal(1.2345789D);
+		setScale2 = setScale1.setScale(4, BigDecimal.ROUND_HALF_EVEN);
+		assertTrue(
+				"the number 1.2345789 after setting scale to 4/ROUND_HALF_EVEN is wrong",
+				setScale2.doubleValue() == 1.2346D && setScale2.scale() == 4);
+		setNeg = new BigDecimal(-1.2335789D);
+		setScale2 = setNeg.setScale(2, BigDecimal.ROUND_HALF_EVEN);
+		assertTrue(
+				"the number -1.2335789 after setting scale to 2/ROUND_HALF_EVEN is wrong",
+				setScale2.doubleValue() == -1.23D && setScale2.scale() == 2);
+		setScale2 = new BigDecimal("1.2345000").setScale(3,
+				BigDecimal.ROUND_HALF_EVEN);
+		assertTrue(
+				"the number 1.2345789 after setting scale to 3/ROUND_HALF_EVEN is wrong",
+				setScale2.doubleValue() == 1.234D && setScale2.scale() == 3);
+		setScale2 = new BigDecimal("-1.2345000").setScale(3,
+				BigDecimal.ROUND_HALF_EVEN);
+		assertTrue(
+				"the number -1.2335789 after setting scale to 3/ROUND_HALF_EVEN is wrong",
+				setScale2.doubleValue() == -1.234D && setScale2.scale() == 3);
+
+		// testing rounding Mode ROUND_HALF_UP
+		setScale1 = new BigDecimal("134567.34650");
+		setScale2 = setScale1.setScale(3, BigDecimal.ROUND_HALF_UP);
+		assertTrue(
+				"the number 134567.34658 after setting scale to 3/ROUND_HALF_UP is wrong",
+				setScale2.toString().equals("134567.347")
+						&& setScale2.scale() == 3);
+		setNeg = new BigDecimal("-1234.4567");
+		setScale2 = setNeg.setScale(0, BigDecimal.ROUND_HALF_UP);
+		assertTrue(
+				"the number -1234.4567 after setting scale to 0/ROUND_HALF_UP is wrong",
+				setScale2.toString().equals("-1234") && setScale2.scale() == 0);
+
+		// testing rounding Mode ROUND_UNNECESSARY
+		try {
+			setScale1.setScale(3, BigDecimal.ROUND_UNNECESSARY);
+            fail("arithmetic Exception not caught for round unnecessary");
+		} catch (ArithmeticException e) {
+		}
+
+		// testing rounding Mode ROUND_UP
+		setScale1 = new BigDecimal("100000.374");
+		setScale2 = setScale1.setScale(2, BigDecimal.ROUND_UP);
+		assertTrue(
+				"the number 100000.374 after setting scale to 2/ROUND_UP is wrong",
+				setScale2.toString().equals("100000.38")
+						&& setScale2.scale() == 2);
+		setNeg = new BigDecimal(-134.34589D);
+		setScale2 = setNeg.setScale(2, BigDecimal.ROUND_UP);
+		assertTrue(
+				"the number -134.34589 after setting scale to 2/ROUND_UP is wrong",
+				setScale2.doubleValue() == -134.35D && setScale2.scale() == 2);
+
+		// testing invalid rounding modes
+		try {
+			setScale2 = setScale1.setScale(0, -123);
+            fail("IllegalArgumentException is not caught for wrong rounding mode");
+		} catch (IllegalArgumentException e) {
+		}
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#signum()
+	 */
+	public void test_signum() {
+		BigDecimal sign = new BigDecimal(123E-104);
+		assertTrue("123E-104 is not positive in signum()", sign.signum() == 1);
+		sign = new BigDecimal("-1234.3959");
+		assertTrue("-1234.3959 is not negative in signum()",
+				sign.signum() == -1);
+		sign = new BigDecimal(000D);
+		assertTrue("000D is not zero in signum()", sign.signum() == 0);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#subtract(java.math.BigDecimal)
+	 */
+	public void test_subtractLjava_math_BigDecimal() {
+		BigDecimal sub1 = new BigDecimal("13948");
+		BigDecimal sub2 = new BigDecimal("2839.489");
+		BigDecimal result = sub1.subtract(sub2);
+		assertTrue("13948 - 2839.489 is wrong: " + result, result.toString()
+				.equals("11108.511")
+				&& result.scale() == 3);
+		BigDecimal result2 = sub2.subtract(sub1);
+		assertTrue("2839.489 - 13948 is wrong", result2.toString().equals(
+				"-11108.511")
+				&& result2.scale() == 3);
+		assertTrue("13948 - 2839.489 is not the negative of 2839.489 - 13948",
+				result.equals(result2.negate()));
+		sub1 = new BigDecimal(value, 1);
+		sub2 = new BigDecimal("0");
+		result = sub1.subtract(sub2);
+		assertTrue("1234590.8 - 0 is wrong", result.equals(sub1));
+		sub1 = new BigDecimal(1.234E-03);
+		sub2 = new BigDecimal(3.423E-10);
+		result = sub1.subtract(sub2);
+		assertTrue("1.234E-03 - 3.423E-10 is wrong, " + result.doubleValue(),
+				result.doubleValue() == 0.0012339996577);
+		sub1 = new BigDecimal(1234.0123);
+		sub2 = new BigDecimal(1234.0123000);
+		result = sub1.subtract(sub2);
+		assertTrue("1234.0123 - 1234.0123000 is wrong, " + result.doubleValue(),
+				result.doubleValue() == 0.0);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#toBigInteger()
+	 */
+	public void test_toBigInteger() {
+		BigDecimal sub1 = new BigDecimal("-29830.989");
+		BigInteger result = sub1.toBigInteger();
+
+		assertTrue("the bigInteger equivalent of -29830.989 is wrong", result
+				.toString().equals("-29830"));
+		sub1 = new BigDecimal(-2837E10);
+		result = sub1.toBigInteger();
+		assertTrue("the bigInteger equivalent of -2837E10 is wrong", result
+				.doubleValue() == -2837E10);
+		sub1 = new BigDecimal(2.349E-10);
+		result = sub1.toBigInteger();
+		assertTrue("the bigInteger equivalent of 2.349E-10 is wrong", result
+				.equals(BigInteger.ZERO));
+		sub1 = new BigDecimal(value2, 6);
+		result = sub1.toBigInteger();
+		assertTrue("the bigInteger equivalent of 12334.560000 is wrong", result
+				.toString().equals("12334"));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#toString()
+	 */
+	public void test_toString() {
+		BigDecimal toString1 = new BigDecimal("1234.000");
+		assertTrue("the toString representation of 1234.000 is wrong",
+				toString1.toString().equals("1234.000"));
+		toString1 = new BigDecimal("-123.4E-5");
+		assertTrue("the toString representation of -123.4E-5 is wrong: "
+				+ toString1, toString1.toString().equals("-0.001234"));
+		toString1 = new BigDecimal("-1.455E-20");
+		assertTrue("the toString representation of -1.455E-20 is wrong",
+				toString1.toString().equals("-1.455E-20"));
+		toString1 = new BigDecimal(value2, 4);
+		assertTrue("the toString representation of 1233456.0000 is wrong",
+				toString1.toString().equals("1233456.0000"));
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#unscaledValue()
+	 */
+	public void test_unscaledValue() {
+		BigDecimal unsVal = new BigDecimal("-2839485.000");
+		assertTrue("the unscaledValue of -2839485.000 is wrong", unsVal
+				.unscaledValue().toString().equals("-2839485000"));
+		unsVal = new BigDecimal(123E10);
+		assertTrue("the unscaledValue of 123E10 is wrong", unsVal
+				.unscaledValue().toString().equals("1230000000000"));
+		unsVal = new BigDecimal("-4.56E-13");
+		assertTrue("the unscaledValue of -4.56E-13 is wrong: "
+				+ unsVal.unscaledValue(), unsVal.unscaledValue().toString()
+				.equals("-456"));
+		unsVal = new BigDecimal(value, 3);
+		assertTrue("the unscaledValue of 12345.908 is wrong", unsVal
+				.unscaledValue().toString().equals("12345908"));
+
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#valueOf(long)
+	 */
+	public void test_valueOfJ() {
+		BigDecimal valueOfL = BigDecimal.valueOf(9223372036854775806L);
+		assertTrue("the bigDecimal equivalent of 9223372036854775806 is wrong",
+				valueOfL.unscaledValue().toString().equals(
+						"9223372036854775806")
+						&& valueOfL.scale() == 0);
+		assertTrue(
+				"the toString representation of 9223372036854775806 is wrong",
+				valueOfL.toString().equals("9223372036854775806"));
+		valueOfL = BigDecimal.valueOf(0L);
+		assertTrue("the bigDecimal equivalent of 0 is wrong", valueOfL
+				.unscaledValue().toString().equals("0")
+				&& valueOfL.scale() == 0);
+	}
+
+	/**
+	 * @tests java.math.BigDecimal#valueOf(long, int)
+	 */
+	public void test_valueOfJI() {
+		BigDecimal valueOfJI = BigDecimal.valueOf(9223372036854775806L, 5);
+		assertTrue(
+				"the bigDecimal equivalent of 92233720368547.75806 is wrong",
+				valueOfJI.unscaledValue().toString().equals(
+						"9223372036854775806")
+						&& valueOfJI.scale() == 5);
+		assertTrue(
+				"the toString representation of 9223372036854775806 is wrong",
+				valueOfJI.toString().equals("92233720368547.75806"));
+		valueOfJI = BigDecimal.valueOf(1234L, 8);
+		assertTrue(
+				"the bigDecimal equivalent of 92233720368547.75806 is wrong",
+				valueOfJI.unscaledValue().toString().equals("1234")
+						&& valueOfJI.scale() == 8);
+		assertTrue(
+				"the toString representation of 9223372036854775806 is wrong",
+				valueOfJI.toString().equals("0.00001234"));
+		valueOfJI = BigDecimal.valueOf(0, 3);
+		assertTrue(
+				"the bigDecimal equivalent of 92233720368547.75806 is wrong",
+				valueOfJI.unscaledValue().toString().equals("0")
+						&& valueOfJI.scale() == 3);
+		assertTrue(
+				"the toString representation of 9223372036854775806 is wrong",
+				valueOfJI.toString().equals("0.000"));
+
+	}
+
+	public void test_BigDecimal_serialization() throws Exception {
+        // Regression for HARMONY-1896
+        char[] in = { '1', '5', '6', '7', '8', '7', '.', '0', '0' };
+        BigDecimal bd = new BigDecimal(in, 0, 9);
+
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(bos);
+        oos.writeObject(bd);
+
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        ObjectInputStream ois = new ObjectInputStream(bis);
+        BigDecimal nbd = (BigDecimal) ois.readObject();
+
+        assertEquals(bd.intValue(), nbd.intValue());
+        assertEquals(bd.doubleValue(), nbd.doubleValue(), 0.0);
+        assertEquals(bd.toString(), nbd.toString());
+    }
+	
+	/**
+	 * @tests java.math.BigDecimal#stripTrailingZero(long)
+	 */
+	public void test_stripTrailingZero() {
+		BigDecimal sixhundredtest = new BigDecimal("600.0");
+		assertTrue("stripTrailingZero failed for 600.0",
+				((sixhundredtest.stripTrailingZeros()).scale() == -2)
+				);
+		
+		/* Single digit, no trailing zero, odd number */
+		BigDecimal notrailingzerotest = new BigDecimal("1");
+		assertTrue("stripTrailingZero failed for 1",
+				((notrailingzerotest.stripTrailingZeros()).scale() == 0)
+				);
+		
+                // BEGIN android-changed: preserve RI compatibility, so BigDecimal.equals (which checks
+                // value *and* scale) continues to work. https://issues.apache.org/jira/browse/HARMONY-4623
+		/* Zero */
+		BigDecimal zerotest = new BigDecimal("0.0000");
+                assertEquals("stripTrailingZero failed for 0.0000", 4, zerotest.stripTrailingZeros().scale());
+	}	
+
+	public void testMathContextConstruction() {
+        String a = "-12380945E+61";
+        BigDecimal aNumber = new BigDecimal(a);
+        int precision = 6;
+        RoundingMode rm = RoundingMode.HALF_DOWN;
+        MathContext mcIntRm = new MathContext(precision, rm);
+        MathContext mcStr = new MathContext("precision=6 roundingMode=HALF_DOWN");
+        MathContext mcInt = new MathContext(precision);
+        BigDecimal res = aNumber.abs(mcInt);
+        assertEquals("MathContext Constructer with int precision failed",
+                res, 
+                new BigDecimal("1.23809E+68"));
+        
+        assertEquals("Equal MathContexts are not Equal ",
+                mcIntRm,
+                mcStr);
+        
+        assertEquals("Different MathContext are reported as Equal ",
+        		mcInt.equals(mcStr),
+                false);
+        
+        assertEquals("Equal MathContexts have different hashcodes ",
+                mcIntRm.hashCode(),
+                mcStr.hashCode());
+       
+        assertEquals("MathContext.toString() returning incorrect value",
+                mcIntRm.toString(),
+                "precision=6 roundingMode=HALF_DOWN");
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/math/BigIntegerTest.java b/harmony-tests/src/test/java/tests/api/java/math/BigIntegerTest.java
new file mode 100644
index 0000000..28995cb
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/math/BigIntegerTest.java
@@ -0,0 +1,988 @@
+/*
+ *  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 tests.api.java.math;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+public class BigIntegerTest extends junit.framework.TestCase {
+
+	BigInteger minusTwo = new BigInteger("-2", 10);
+
+	BigInteger minusOne = new BigInteger("-1", 10);
+
+	BigInteger zero = new BigInteger("0", 10);
+
+	BigInteger one = new BigInteger("1", 10);
+
+	BigInteger two = new BigInteger("2", 10);
+
+	BigInteger ten = new BigInteger("10", 10);
+
+	BigInteger sixteen = new BigInteger("16", 10);
+
+	BigInteger oneThousand = new BigInteger("1000", 10);
+
+	BigInteger aZillion = new BigInteger(
+			"100000000000000000000000000000000000000000000000000", 10);
+
+	BigInteger twoToTheTen = new BigInteger("1024", 10);
+
+	BigInteger twoToTheSeventy = two.pow(70);
+
+	Random rand = new Random();
+
+	BigInteger bi;
+
+	BigInteger bi1;
+
+	BigInteger bi2;
+
+	BigInteger bi3;
+
+	BigInteger bi11;
+
+	BigInteger bi22;
+
+	BigInteger bi33;
+
+	BigInteger bi12;
+
+	BigInteger bi23;
+
+	BigInteger bi13;
+
+	BigInteger largePos;
+
+	BigInteger smallPos;
+
+	BigInteger largeNeg;
+
+	BigInteger smallNeg;
+
+	BigInteger[][] booleanPairs;
+
+	/**
+	 * @tests java.math.BigInteger#BigInteger(int, java.util.Random)
+	 */
+	public void test_ConstructorILjava_util_Random() {
+        // regression test for HARMONY-1047
+		try {
+			new BigInteger(Integer.MAX_VALUE, (Random)null);
+			fail("NegativeArraySizeException expected");
+		} catch (NegativeArraySizeException e) {
+            // PASSED
+		}
+		
+		bi = new BigInteger(70, rand);
+		bi2 = new BigInteger(70, rand);
+		assertTrue("Random number is negative", bi.compareTo(zero) >= 0);
+		assertTrue("Random number is too big",
+				bi.compareTo(twoToTheSeventy) < 0);
+		assertTrue(
+				"Two random numbers in a row are the same (might not be a bug but it very likely is)",
+				!bi.equals(bi2));
+		assertTrue("Not zero", new BigInteger(0, rand).equals(BigInteger.ZERO));
+	}
+
+	/**
+	 * @tests java.math.BigInteger#BigInteger(byte[])
+	 */
+	public void test_Constructor$B() {
+		byte[] myByteArray;
+		myByteArray = new byte[] { (byte) 0x00, (byte) 0xFF, (byte) 0xFE };
+		bi = new BigInteger(myByteArray);
+		assertTrue("Incorrect value for pos number", bi.equals(BigInteger.ZERO
+				.setBit(16).subtract(two)));
+		myByteArray = new byte[] { (byte) 0xFF, (byte) 0xFE };
+		bi = new BigInteger(myByteArray);
+		assertTrue("Incorrect value for neg number", bi.equals(minusTwo));
+	}
+
+	/**
+	 * @tests java.math.BigInteger#BigInteger(int, byte[])
+	 */
+	public void test_ConstructorI$B() {
+		byte[] myByteArray;
+		myByteArray = new byte[] { (byte) 0xFF, (byte) 0xFE };
+		bi = new BigInteger(1, myByteArray);
+		assertTrue("Incorrect value for pos number", bi.equals(BigInteger.ZERO
+				.setBit(16).subtract(two)));
+		bi = new BigInteger(-1, myByteArray);
+		assertTrue("Incorrect value for neg number", bi.equals(BigInteger.ZERO
+				.setBit(16).subtract(two).negate()));
+		myByteArray = new byte[] { (byte) 0, (byte) 0 };
+		bi = new BigInteger(0, myByteArray);
+		assertTrue("Incorrect value for zero", bi.equals(zero));
+		myByteArray = new byte[] { (byte) 1 };
+		try {
+			new BigInteger(0, myByteArray);
+            fail("Failed to throw NumberFormatException");
+		} catch (NumberFormatException e) {
+			// correct
+		}
+	}
+	
+	/**
+	 * @tests java.math.BigInteger#BigInteger(java.lang.String)
+	 */
+	public void test_constructor_String_empty() {
+		try {
+			new BigInteger("");			
+            fail("Expected NumberFormatException for new BigInteger(\"\")");
+		} catch (NumberFormatException e) {
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#toByteArray()
+	 */
+	public void test_toByteArray() {
+		byte[] myByteArray, anotherByteArray;
+		myByteArray = new byte[] { 97, 33, 120, 124, 50, 2, 0, 0, 0, 12, 124,
+				42 };
+		anotherByteArray = new BigInteger(myByteArray).toByteArray();
+		assertTrue("Incorrect byte array returned",
+				myByteArray.length == anotherByteArray.length);
+		for (int counter = myByteArray.length - 1; counter >= 0; counter--) {
+			assertTrue("Incorrect values in returned byte array",
+					myByteArray[counter] == anotherByteArray[counter]);
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#isProbablePrime(int)
+	 */
+	public void test_isProbablePrimeI() {
+		int fails = 0;
+		bi = new BigInteger(20, 20, rand);
+		if (!bi.isProbablePrime(17)) {
+            fails++;
+        }
+		bi = new BigInteger("4", 10);
+		if (bi.isProbablePrime(17)) {
+            fail("isProbablePrime failed for: " + bi);
+        }
+		bi = BigInteger.valueOf(17L * 13L);
+		if (bi.isProbablePrime(17)) {
+            fail("isProbablePrime failed for: " + bi);
+        }
+		for (long a = 2; a < 1000; a++) {
+            if (isPrime(a)) {
+                assertTrue("false negative on prime number <1000", BigInteger
+						.valueOf(a).isProbablePrime(5));
+            } else if (BigInteger.valueOf(a).isProbablePrime(17)) {
+				System.out.println("isProbablePrime failed for: " + a);
+				fails++;
+			}
+        }
+		for (int a = 0; a < 1000; a++) {
+			bi = BigInteger.valueOf(rand.nextInt(1000000)).multiply(
+					BigInteger.valueOf(rand.nextInt(1000000)));
+			if (bi.isProbablePrime(17)) {
+				System.out.println("isProbablePrime failed for: " + bi);
+				fails++;
+			}
+		}
+		for (int a = 0; a < 200; a++) {
+			bi = new BigInteger(70, rand).multiply(new BigInteger(70, rand));
+			if (bi.isProbablePrime(17)) {
+				System.out.println("isProbablePrime failed for: " + bi);
+				fails++;
+			}
+		}
+		assertTrue("Too many false positives - may indicate a problem",
+				fails <= 1);
+	}
+
+	/**
+	 * @tests java.math.BigInteger#equals(java.lang.Object)
+	 */
+	public void test_equalsLjava_lang_Object() {
+		assertTrue("0=0", zero.equals(BigInteger.valueOf(0)));
+		assertTrue("-123=-123", BigInteger.valueOf(-123).equals(
+				BigInteger.valueOf(-123)));
+		assertTrue("0=1", !zero.equals(one));
+		assertTrue("0=-1", !zero.equals(minusOne));
+		assertTrue("1=-1", !one.equals(minusOne));
+		assertTrue("bi3=bi3", bi3.equals(bi3));
+		assertTrue("bi3=copy of bi3", bi3.equals(bi3.negate().negate()));
+		assertTrue("bi3=bi2", !bi3.equals(bi2));
+	}
+
+	/**
+	 * @tests java.math.BigInteger#compareTo(java.math.BigInteger)
+	 */
+	public void test_compareToLjava_math_BigInteger() {
+		assertTrue("Smaller number returned >= 0", one.compareTo(two) < 0);
+		assertTrue("Larger number returned >= 0", two.compareTo(one) > 0);
+		assertTrue("Equal numbers did not return 0", one.compareTo(one) == 0);
+		assertTrue("Neg number messed things up",
+				two.negate().compareTo(one) < 0);
+	}
+
+	/**
+	 * @tests java.math.BigInteger#intValue()
+	 */
+	public void test_intValue() {
+		assertTrue("Incorrect intValue for 2**70",
+				twoToTheSeventy.intValue() == 0);
+		assertTrue("Incorrect intValue for 2", two.intValue() == 2);
+	}
+
+	/**
+	 * @tests java.math.BigInteger#longValue()
+	 */
+	public void test_longValue() {
+		assertTrue("Incorrect longValue for 2**70",
+				twoToTheSeventy.longValue() == 0);
+		assertTrue("Incorrect longValue for 2", two.longValue() == 2);
+	}
+
+	/**
+	 * @tests java.math.BigInteger#valueOf(long)
+	 */
+	public void test_valueOfJ() {
+		assertTrue("Incurred number returned for 2", BigInteger.valueOf(2L)
+				.equals(two));
+		assertTrue("Incurred number returned for 200", BigInteger.valueOf(200L)
+				.equals(BigInteger.valueOf(139).add(BigInteger.valueOf(61))));
+	}
+
+	/**
+	 * @tests java.math.BigInteger#add(java.math.BigInteger)
+	 */
+	public void test_addLjava_math_BigInteger() {
+		assertTrue("Incorrect sum--wanted a zillion", aZillion.add(aZillion)
+				.add(aZillion.negate()).equals(aZillion));
+		assertTrue("0+0", zero.add(zero).equals(zero));
+		assertTrue("0+1", zero.add(one).equals(one));
+		assertTrue("1+0", one.add(zero).equals(one));
+		assertTrue("1+1", one.add(one).equals(two));
+		assertTrue("0+(-1)", zero.add(minusOne).equals(minusOne));
+		assertTrue("(-1)+0", minusOne.add(zero).equals(minusOne));
+		assertTrue("(-1)+(-1)", minusOne.add(minusOne).equals(minusTwo));
+		assertTrue("1+(-1)", one.add(minusOne).equals(zero));
+		assertTrue("(-1)+1", minusOne.add(one).equals(zero));
+
+		for (int i = 0; i < 200; i++) {
+			BigInteger midbit = zero.setBit(i);
+			assertTrue("add fails to carry on bit " + i, midbit.add(midbit)
+					.equals(zero.setBit(i + 1)));
+		}
+		BigInteger bi2p3 = bi2.add(bi3);
+		BigInteger bi3p2 = bi3.add(bi2);
+		assertTrue("bi2p3=bi3p2", bi2p3.equals(bi3p2));
+
+		// add large positive + small positive
+
+		// add large positive + small negative
+
+		// add large negative + small positive
+
+		// add large negative + small negative
+	}
+
+	/**
+	 * @tests java.math.BigInteger#negate()
+	 */
+	public void test_negate() {
+		assertTrue("Single negation of zero did not result in zero", zero
+				.negate().equals(zero));
+		assertTrue("Single negation resulted in original nonzero number",
+				!aZillion.negate().equals(aZillion));
+		assertTrue("Double negation did not result in original number",
+				aZillion.negate().negate().equals(aZillion));
+
+		assertTrue("0.neg", zero.negate().equals(zero));
+		assertTrue("1.neg", one.negate().equals(minusOne));
+		assertTrue("2.neg", two.negate().equals(minusTwo));
+		assertTrue("-1.neg", minusOne.negate().equals(one));
+		assertTrue("-2.neg", minusTwo.negate().equals(two));
+		assertTrue("0x62EB40FEF85AA9EBL*2.neg", BigInteger.valueOf(
+				0x62EB40FEF85AA9EBL * 2).negate().equals(
+				BigInteger.valueOf(-0x62EB40FEF85AA9EBL * 2)));
+		for (int i = 0; i < 200; i++) {
+			BigInteger midbit = zero.setBit(i);
+			BigInteger negate = midbit.negate();
+			assertTrue("negate negate", negate.negate().equals(midbit));
+			assertTrue("neg fails on bit " + i, midbit.negate().add(midbit)
+					.equals(zero));
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#signum()
+	 */
+	public void test_signum() {
+		assertTrue("Wrong positive signum", two.signum() == 1);
+		assertTrue("Wrong zero signum", zero.signum() == 0);
+		assertTrue("Wrong neg zero signum", zero.negate().signum() == 0);
+		assertTrue("Wrong neg signum", two.negate().signum() == -1);
+	}
+
+	/**
+	 * @tests java.math.BigInteger#abs()
+	 */
+	public void test_abs() {
+		assertTrue("Invalid number returned for zillion", aZillion.negate()
+				.abs().equals(aZillion.abs()));
+		assertTrue("Invalid number returned for zero neg", zero.negate().abs()
+				.equals(zero));
+		assertTrue("Invalid number returned for zero", zero.abs().equals(zero));
+		assertTrue("Invalid number returned for two", two.negate().abs()
+				.equals(two));
+	}
+
+	/**
+	 * @tests java.math.BigInteger#pow(int)
+	 */
+	public void test_powI() {
+		assertTrue("Incorrect exponent returned for 2**10", two.pow(10).equals(
+				twoToTheTen));
+		assertTrue("Incorrect exponent returned for 2**70", two.pow(30)
+				.multiply(two.pow(40)).equals(twoToTheSeventy));
+		assertTrue("Incorrect exponent returned for 10**50", ten.pow(50)
+				.equals(aZillion));
+	}
+
+	/**
+	 * @tests java.math.BigInteger#modInverse(java.math.BigInteger)
+	 */
+	public void test_modInverseLjava_math_BigInteger() {
+		BigInteger a = zero, mod, inv;
+		for (int j = 3; j < 50; j++) {
+			mod = BigInteger.valueOf(j);
+			for (int i = -j + 1; i < j; i++) {
+                try {
+					a = BigInteger.valueOf(i);
+					inv = a.modInverse(mod);
+					assertTrue("bad inverse: " + a + " inv mod " + mod
+							+ " equals " + inv, one.equals(a.multiply(inv).mod(
+							mod)));
+					assertTrue("inverse greater than modulo: " + a
+							+ " inv mod " + mod + " equals " + inv, inv
+							.compareTo(mod) < 0);
+					assertTrue("inverse less than zero: " + a + " inv mod "
+							+ mod + " equals " + inv, inv
+							.compareTo(BigInteger.ZERO) >= 0);
+				} catch (ArithmeticException e) {
+					assertTrue("should have found inverse for " + a + " mod "
+							+ mod, !one.equals(a.gcd(mod)));
+				}
+            }
+		}
+		for (int j = 1; j < 10; j++) {
+			mod = bi2.add(BigInteger.valueOf(j));
+			for (int i = 0; i < 20; i++) {
+                try {
+					a = bi3.add(BigInteger.valueOf(i));
+					inv = a.modInverse(mod);
+					assertTrue("bad inverse: " + a + " inv mod " + mod
+							+ " equals " + inv, one.equals(a.multiply(inv).mod(
+							mod)));
+					assertTrue("inverse greater than modulo: " + a
+							+ " inv mod " + mod + " equals " + inv, inv
+							.compareTo(mod) < 0);
+					assertTrue("inverse less than zero: " + a + " inv mod "
+							+ mod + " equals " + inv, inv
+							.compareTo(BigInteger.ZERO) >= 0);
+				} catch (ArithmeticException e) {
+					assertTrue("should have found inverse for " + a + " mod "
+							+ mod, !one.equals(a.gcd(mod)));
+				}
+            }
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#shiftRight(int)
+	 */
+	public void test_shiftRightI() {
+		assertTrue("1 >> 0", BigInteger.valueOf(1).shiftRight(0).equals(
+				BigInteger.ONE));
+		assertTrue("1 >> 1", BigInteger.valueOf(1).shiftRight(1).equals(
+				BigInteger.ZERO));
+		assertTrue("1 >> 63", BigInteger.valueOf(1).shiftRight(63).equals(
+				BigInteger.ZERO));
+		assertTrue("1 >> 64", BigInteger.valueOf(1).shiftRight(64).equals(
+				BigInteger.ZERO));
+		assertTrue("1 >> 65", BigInteger.valueOf(1).shiftRight(65).equals(
+				BigInteger.ZERO));
+		assertTrue("1 >> 1000", BigInteger.valueOf(1).shiftRight(1000).equals(
+				BigInteger.ZERO));
+		assertTrue("-1 >> 0", BigInteger.valueOf(-1).shiftRight(0).equals(
+				minusOne));
+		assertTrue("-1 >> 1", BigInteger.valueOf(-1).shiftRight(1).equals(
+				minusOne));
+		assertTrue("-1 >> 63", BigInteger.valueOf(-1).shiftRight(63).equals(
+				minusOne));
+		assertTrue("-1 >> 64", BigInteger.valueOf(-1).shiftRight(64).equals(
+				minusOne));
+		assertTrue("-1 >> 65", BigInteger.valueOf(-1).shiftRight(65).equals(
+				minusOne));
+		assertTrue("-1 >> 1000", BigInteger.valueOf(-1).shiftRight(1000)
+				.equals(minusOne));
+
+		BigInteger a = BigInteger.ONE;
+		BigInteger c = bi3;
+		BigInteger E = bi3.negate();
+		BigInteger e = E;
+		for (int i = 0; i < 200; i++) {
+			BigInteger b = BigInteger.ZERO.setBit(i);
+			assertTrue("a==b", a.equals(b));
+			a = a.shiftLeft(1);
+			assertTrue("a non-neg", a.signum() >= 0);
+
+			BigInteger d = bi3.shiftRight(i);
+			assertTrue("c==d", c.equals(d));
+			c = c.shiftRight(1);
+			assertTrue(">>1 == /2", d.divide(two).equals(c));
+			assertTrue("c non-neg", c.signum() >= 0);
+
+			BigInteger f = E.shiftRight(i);
+			assertTrue("e==f", e.equals(f));
+			e = e.shiftRight(1);
+			assertTrue(">>1 == /2", f.subtract(one).divide(two).equals(e));
+			assertTrue("e negative", e.signum() == -1);
+
+			assertTrue("b >> i", b.shiftRight(i).equals(one));
+			assertTrue("b >> i+1", b.shiftRight(i + 1).equals(zero));
+			assertTrue("b >> i-1", b.shiftRight(i - 1).equals(two));
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#shiftLeft(int)
+	 */
+	public void test_shiftLeftI() {
+		assertTrue("1 << 0", one.shiftLeft(0).equals(one));
+		assertTrue("1 << 1", one.shiftLeft(1).equals(two));
+		assertTrue("1 << 63", one.shiftLeft(63).equals(
+				new BigInteger("8000000000000000", 16)));
+		assertTrue("1 << 64", one.shiftLeft(64).equals(
+				new BigInteger("10000000000000000", 16)));
+		assertTrue("1 << 65", one.shiftLeft(65).equals(
+				new BigInteger("20000000000000000", 16)));
+		assertTrue("-1 << 0", minusOne.shiftLeft(0).equals(minusOne));
+		assertTrue("-1 << 1", minusOne.shiftLeft(1).equals(minusTwo));
+		assertTrue("-1 << 63", minusOne.shiftLeft(63).equals(
+				new BigInteger("-9223372036854775808")));
+		assertTrue("-1 << 64", minusOne.shiftLeft(64).equals(
+				new BigInteger("-18446744073709551616")));
+		assertTrue("-1 << 65", minusOne.shiftLeft(65).equals(
+				new BigInteger("-36893488147419103232")));
+
+		BigInteger a = bi3;
+		BigInteger c = minusOne;
+		for (int i = 0; i < 200; i++) {
+			BigInteger b = bi3.shiftLeft(i);
+			assertTrue("a==b", a.equals(b));
+			assertTrue("a >> i == bi3", a.shiftRight(i).equals(bi3));
+			a = a.shiftLeft(1);
+			assertTrue("<<1 == *2", b.multiply(two).equals(a));
+			assertTrue("a non-neg", a.signum() >= 0);
+			assertTrue("a.bitCount==b.bitCount", a.bitCount() == b.bitCount());
+
+			BigInteger d = minusOne.shiftLeft(i);
+			assertTrue("c==d", c.equals(d));
+			c = c.shiftLeft(1);
+			assertTrue("<<1 == *2 negative", d.multiply(two).equals(c));
+			assertTrue("c negative", c.signum() == -1);
+			assertTrue("d >> i == minusOne", d.shiftRight(i).equals(minusOne));
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#multiply(java.math.BigInteger)
+	 */
+	public void test_multiplyLjava_math_BigInteger() {
+		assertTrue("Incorrect sum--wanted three zillion", aZillion
+				.add(aZillion).add(aZillion).equals(
+						aZillion.multiply(new BigInteger("3", 10))));
+
+		assertTrue("0*0", zero.multiply(zero).equals(zero));
+		assertTrue("0*1", zero.multiply(one).equals(zero));
+		assertTrue("1*0", one.multiply(zero).equals(zero));
+		assertTrue("1*1", one.multiply(one).equals(one));
+		assertTrue("0*(-1)", zero.multiply(minusOne).equals(zero));
+		assertTrue("(-1)*0", minusOne.multiply(zero).equals(zero));
+		assertTrue("(-1)*(-1)", minusOne.multiply(minusOne).equals(one));
+		assertTrue("1*(-1)", one.multiply(minusOne).equals(minusOne));
+		assertTrue("(-1)*1", minusOne.multiply(one).equals(minusOne));
+
+		testAllMults(bi1, bi1, bi11);
+		testAllMults(bi2, bi2, bi22);
+		testAllMults(bi3, bi3, bi33);
+		testAllMults(bi1, bi2, bi12);
+		testAllMults(bi1, bi3, bi13);
+		testAllMults(bi2, bi3, bi23);
+	}
+
+	/**
+	 * @tests java.math.BigInteger#divide(java.math.BigInteger)
+	 */
+	public void test_divideLjava_math_BigInteger() {
+		testAllDivs(bi33, bi3);
+		testAllDivs(bi22, bi2);
+		testAllDivs(bi11, bi1);
+		testAllDivs(bi13, bi1);
+		testAllDivs(bi13, bi3);
+		testAllDivs(bi12, bi1);
+		testAllDivs(bi12, bi2);
+		testAllDivs(bi23, bi2);
+		testAllDivs(bi23, bi3);
+		testAllDivs(largePos, bi1);
+		testAllDivs(largePos, bi2);
+		testAllDivs(largePos, bi3);
+		testAllDivs(largeNeg, bi1);
+		testAllDivs(largeNeg, bi2);
+		testAllDivs(largeNeg, bi3);
+		testAllDivs(largeNeg, largePos);
+		testAllDivs(largePos, largeNeg);
+		testAllDivs(bi3, bi3);
+		testAllDivs(bi2, bi2);
+		testAllDivs(bi1, bi1);
+		testDivRanges(bi1);
+		testDivRanges(bi2);
+		testDivRanges(bi3);
+		testDivRanges(smallPos);
+		testDivRanges(largePos);
+		testDivRanges(new BigInteger("62EB40FEF85AA9EB", 16));
+		testAllDivs(BigInteger.valueOf(0xCC0225953CL), BigInteger
+				.valueOf(0x1B937B765L));
+
+		try {
+			largePos.divide(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			bi1.divide(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			bi3.negate().divide(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			zero.divide(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#remainder(java.math.BigInteger)
+	 */
+	public void test_remainderLjava_math_BigInteger() {
+		try {
+			largePos.remainder(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			bi1.remainder(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			bi3.negate().remainder(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			zero.remainder(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#mod(java.math.BigInteger)
+	 */
+	public void test_modLjava_math_BigInteger() {
+		try {
+			largePos.mod(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			bi1.mod(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			bi3.negate().mod(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			zero.mod(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#divideAndRemainder(java.math.BigInteger)
+	 */
+	public void test_divideAndRemainderLjava_math_BigInteger() {
+		try {
+			largePos.divideAndRemainder(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			bi1.divideAndRemainder(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			bi3.negate().divideAndRemainder(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+
+		try {
+			zero.divideAndRemainder(zero);
+            fail("ArithmeticException expected");
+		} catch (ArithmeticException e) {
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#BigInteger(java.lang.String)
+	 */
+	public void test_ConstructorLjava_lang_String() {
+		assertTrue("new(0)", new BigInteger("0").equals(BigInteger.valueOf(0)));
+		assertTrue("new(1)", new BigInteger("1").equals(BigInteger.valueOf(1)));
+		assertTrue("new(12345678901234)", new BigInteger("12345678901234")
+				.equals(BigInteger.valueOf(12345678901234L)));
+		assertTrue("new(-1)", new BigInteger("-1").equals(BigInteger
+				.valueOf(-1)));
+		assertTrue("new(-12345678901234)", new BigInteger("-12345678901234")
+				.equals(BigInteger.valueOf(-12345678901234L)));
+	}
+
+	/**
+	 * @tests java.math.BigInteger#BigInteger(java.lang.String, int)
+	 */
+	public void test_ConstructorLjava_lang_StringI() {
+		assertTrue("new(0,16)", new BigInteger("0", 16).equals(BigInteger
+				.valueOf(0)));
+		assertTrue("new(1,16)", new BigInteger("1", 16).equals(BigInteger
+				.valueOf(1)));
+		assertTrue("new(ABF345678901234,16)", new BigInteger("ABF345678901234",
+				16).equals(BigInteger.valueOf(0xABF345678901234L)));
+		assertTrue("new(abf345678901234,16)", new BigInteger("abf345678901234",
+				16).equals(BigInteger.valueOf(0xABF345678901234L)));
+		assertTrue("new(-1,16)", new BigInteger("-1", 16).equals(BigInteger
+				.valueOf(-1)));
+		assertTrue("new(-ABF345678901234,16)", new BigInteger(
+				"-ABF345678901234", 16).equals(BigInteger
+				.valueOf(-0xABF345678901234L)));
+		assertTrue("new(-abf345678901234,16)", new BigInteger(
+				"-abf345678901234", 16).equals(BigInteger
+				.valueOf(-0xABF345678901234L)));
+		assertTrue("new(-101010101,2)", new BigInteger("-101010101", 2)
+				.equals(BigInteger.valueOf(-341)));
+	}
+
+	/**
+	 * @tests java.math.BigInteger#toString()
+	 */
+	public void test_toString() {
+		assertTrue("0.toString", "0".equals(BigInteger.valueOf(0).toString()));
+		assertTrue("1.toString", "1".equals(BigInteger.valueOf(1).toString()));
+		assertTrue("12345678901234.toString", "12345678901234"
+				.equals(BigInteger.valueOf(12345678901234L).toString()));
+		assertTrue("-1.toString", "-1"
+				.equals(BigInteger.valueOf(-1).toString()));
+		assertTrue("-12345678901234.toString", "-12345678901234"
+				.equals(BigInteger.valueOf(-12345678901234L).toString()));
+	}
+
+	/**
+	 * @tests java.math.BigInteger#toString(int)
+	 */
+	public void test_toStringI() {
+		assertTrue("0.toString(16)", "0".equals(BigInteger.valueOf(0).toString(
+				16)));
+		assertTrue("1.toString(16)", "1".equals(BigInteger.valueOf(1).toString(
+				16)));
+		assertTrue("ABF345678901234.toString(16)", "abf345678901234"
+				.equals(BigInteger.valueOf(0xABF345678901234L).toString(16)));
+		assertTrue("-1.toString(16)", "-1".equals(BigInteger.valueOf(-1)
+				.toString(16)));
+		assertTrue("-ABF345678901234.toString(16)", "-abf345678901234"
+				.equals(BigInteger.valueOf(-0xABF345678901234L).toString(16)));
+		assertTrue("-101010101.toString(2)", "-101010101".equals(BigInteger
+				.valueOf(-341).toString(2)));
+	}
+
+	/**
+	 * @tests java.math.BigInteger#and(java.math.BigInteger)
+	 */
+	public void test_andLjava_math_BigInteger() {
+		for (BigInteger[] element : booleanPairs) {
+			BigInteger i1 = element[0], i2 = element[1];
+			BigInteger res = i1.and(i2);
+			assertTrue("symmetry of and", res.equals(i2.and(i1)));
+			int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
+			for (int i = 0; i < len; i++) {
+                assertTrue("and", (i1.testBit(i) && i2.testBit(i)) == res
+						.testBit(i));
+            }
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#or(java.math.BigInteger)
+	 */
+	public void test_orLjava_math_BigInteger() {
+		for (BigInteger[] element : booleanPairs) {
+			BigInteger i1 = element[0], i2 = element[1];
+			BigInteger res = i1.or(i2);
+			assertTrue("symmetry of or", res.equals(i2.or(i1)));
+			int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
+			for (int i = 0; i < len; i++) {
+                assertTrue("or", (i1.testBit(i) || i2.testBit(i)) == res
+						.testBit(i));
+            }
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#xor(java.math.BigInteger)
+	 */
+	public void test_xorLjava_math_BigInteger() {
+		for (BigInteger[] element : booleanPairs) {
+			BigInteger i1 = element[0], i2 = element[1];
+			BigInteger res = i1.xor(i2);
+			assertTrue("symmetry of xor", res.equals(i2.xor(i1)));
+			int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
+			for (int i = 0; i < len; i++) {
+                assertTrue("xor", (i1.testBit(i) ^ i2.testBit(i)) == res
+						.testBit(i));
+            }
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#not()
+	 */
+	public void test_not() {
+		for (BigInteger[] element : booleanPairs) {
+			BigInteger i1 = element[0];
+			BigInteger res = i1.not();
+			int len = i1.bitLength() + 66;
+			for (int i = 0; i < len; i++) {
+                assertTrue("not", !i1.testBit(i) == res.testBit(i));
+            }
+		}
+	}
+
+	/**
+	 * @tests java.math.BigInteger#andNot(java.math.BigInteger)
+	 */
+	public void test_andNotLjava_math_BigInteger() {
+		for (BigInteger[] element : booleanPairs) {
+			BigInteger i1 = element[0], i2 = element[1];
+			BigInteger res = i1.andNot(i2);
+			int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
+			for (int i = 0; i < len; i++) {
+                assertTrue("andNot", (i1.testBit(i) && !i2.testBit(i)) == res
+						.testBit(i));
+            }
+			// asymmetrical
+			i1 = element[1];
+			i2 = element[0];
+			res = i1.andNot(i2);
+			for (int i = 0; i < len; i++) {
+                assertTrue("andNot reversed",
+						(i1.testBit(i) && !i2.testBit(i)) == res.testBit(i));
+            }
+		}
+        //regression for HARMONY-4653
+        try{
+            BigInteger.ZERO.andNot(null);
+            fail("should throw NPE");
+        }catch(Exception e){
+            //expected
+        }
+        BigInteger bi = new BigInteger(0, new byte[]{});
+        assertEquals(BigInteger.ZERO, bi.andNot(BigInteger.ZERO));
+	}
+    
+
+     public void testClone() {
+        // Regression test for HARMONY-1770
+        MyBigInteger myBigInteger = new MyBigInteger("12345");
+        myBigInteger = (MyBigInteger) myBigInteger.clone();
+    }
+
+    static class MyBigInteger extends BigInteger implements Cloneable {
+        public MyBigInteger(String val) {
+            super(val);
+        }
+        public Object clone() {
+            try {
+                return super.clone();
+            } catch (CloneNotSupportedException e) {
+                return null;
+            }
+        }
+    }
+
+	@Override
+    protected void setUp() {
+		bi1 = new BigInteger("2436798324768978", 16);
+		bi2 = new BigInteger("4576829475724387584378543764555", 16);
+		bi3 = new BigInteger("43987298363278574365732645872643587624387563245",
+				16);
+
+		bi33 = new BigInteger(
+				"10730846694701319120609898625733976090865327544790136667944805934175543888691400559249041094474885347922769807001",
+				10);
+		bi22 = new BigInteger(
+				"33301606932171509517158059487795669025817912852219962782230629632224456249",
+				10);
+		bi11 = new BigInteger("6809003003832961306048761258711296064", 10);
+		bi23 = new BigInteger(
+				"597791300268191573513888045771594235932809890963138840086083595706565695943160293610527214057",
+				10);
+		bi13 = new BigInteger(
+				"270307912162948508387666703213038600031041043966215279482940731158968434008",
+				10);
+		bi12 = new BigInteger(
+				"15058244971895641717453176477697767050482947161656458456", 10);
+
+		largePos = new BigInteger(
+				"834759814379857314986743298675687569845986736578576375675678998612743867438632986243982098437620983476924376",
+				16);
+		smallPos = new BigInteger("48753269875973284765874598630960986276", 16);
+		largeNeg = new BigInteger(
+				"-878824397432651481891353247987891423768534321387864361143548364457698487264387568743568743265873246576467643756437657436587436",
+				16);
+		smallNeg = new BigInteger("-567863254343798609857456273458769843", 16);
+		booleanPairs = new BigInteger[][] { { largePos, smallPos },
+				{ largePos, smallNeg }, { largeNeg, smallPos },
+				{ largeNeg, smallNeg } };
+	}
+
+	private void testDiv(BigInteger i1, BigInteger i2) {
+		BigInteger q = i1.divide(i2);
+		BigInteger r = i1.remainder(i2);
+		BigInteger[] temp = i1.divideAndRemainder(i2);
+
+		assertTrue("divide and divideAndRemainder do not agree", q
+				.equals(temp[0]));
+		assertTrue("remainder and divideAndRemainder do not agree", r
+				.equals(temp[1]));
+		assertTrue("signum and equals(zero) do not agree on quotient", q
+				.signum() != 0
+				|| q.equals(zero));
+		assertTrue("signum and equals(zero) do not agree on remainder", r
+				.signum() != 0
+				|| r.equals(zero));
+		assertTrue("wrong sign on quotient", q.signum() == 0
+				|| q.signum() == i1.signum() * i2.signum());
+		assertTrue("wrong sign on remainder", r.signum() == 0
+				|| r.signum() == i1.signum());
+		assertTrue("remainder out of range", r.abs().compareTo(i2.abs()) < 0);
+		assertTrue("quotient too small", q.abs().add(one).multiply(i2.abs())
+				.compareTo(i1.abs()) > 0);
+		assertTrue("quotient too large", q.abs().multiply(i2.abs()).compareTo(
+				i1.abs()) <= 0);
+		BigInteger p = q.multiply(i2);
+		BigInteger a = p.add(r);
+		assertTrue("(a/b)*b+(a%b) != a", a.equals(i1));
+		try {
+			BigInteger mod = i1.mod(i2);
+			assertTrue("mod is negative", mod.signum() >= 0);
+			assertTrue("mod out of range", mod.abs().compareTo(i2.abs()) < 0);
+			assertTrue("positive remainder == mod", r.signum() < 0
+					|| r.equals(mod));
+			assertTrue("negative remainder == mod - divisor", r.signum() >= 0
+					|| r.equals(mod.subtract(i2)));
+		} catch (ArithmeticException e) {
+			assertTrue("mod fails on negative divisor only", i2.signum() <= 0);
+		}
+	}
+
+	private void testDivRanges(BigInteger i) {
+		BigInteger bound = i.multiply(two);
+		for (BigInteger j = bound.negate(); j.compareTo(bound) <= 0; j = j
+				.add(i)) {
+			BigInteger innerbound = j.add(two);
+			BigInteger k = j.subtract(two);
+			for (; k.compareTo(innerbound) <= 0; k = k.add(one)) {
+                testDiv(k, i);
+            }
+		}
+	}
+
+	private boolean isPrime(long b) {
+		if (b == 2) {
+            return true;
+        }
+		// check for div by 2
+		if ((b & 1L) == 0) {
+            return false;
+        }
+		long maxlen = ((long) Math.sqrt(b)) + 2;
+		for (long x = 3; x < maxlen; x += 2) {
+            if (b % x == 0) {
+                return false;
+            }
+        }
+		return true;
+	}
+
+	private void testAllMults(BigInteger i1, BigInteger i2, BigInteger ans) {
+		assertTrue("i1*i2=ans", i1.multiply(i2).equals(ans));
+		assertTrue("i2*i1=ans", i2.multiply(i1).equals(ans));
+		assertTrue("-i1*i2=-ans", i1.negate().multiply(i2).equals(ans.negate()));
+		assertTrue("-i2*i1=-ans", i2.negate().multiply(i1).equals(ans.negate()));
+		assertTrue("i1*-i2=-ans", i1.multiply(i2.negate()).equals(ans.negate()));
+		assertTrue("i2*-i1=-ans", i2.multiply(i1.negate()).equals(ans.negate()));
+		assertTrue("-i1*-i2=ans", i1.negate().multiply(i2.negate()).equals(ans));
+		assertTrue("-i2*-i1=ans", i2.negate().multiply(i1.negate()).equals(ans));
+	}
+
+	private void testAllDivs(BigInteger i1, BigInteger i2) {
+		testDiv(i1, i2);
+		testDiv(i1.negate(), i2);
+		testDiv(i1, i2.negate());
+		testDiv(i1.negate(), i2.negate());
+	}
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetDecoderTest.java
new file mode 100644
index 0000000..a349b9c
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetDecoderTest.java
@@ -0,0 +1,72 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+public class ASCCharsetDecoderTest extends CharsetDecoderTest {
+
+	protected void setUp() throws Exception {
+		cs = Charset.forName("ascii");
+		super.setUp();
+	}
+
+	/*
+	 * @see CharsetDecoderTest#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	// FIXME: give up this tests
+	// public void testDefaultCharsPerByte(){
+	// // assertEquals(1, decoder.averageCharsPerByte());
+	// // assertEquals(1, decoder.maxCharsPerByte());
+	// assertEquals(decoder.averageCharsPerByte(), 1, 0.001);
+	// assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+	// }
+
+	ByteBuffer getUnmappedByteBuffer() {
+		// FIXME: different here
+		return null;
+		// ByteBuffer buffer = ByteBuffer.allocate(8);
+		// buffer.put((byte)-1);
+		// buffer.put(unibytes);
+		// buffer.flip();
+		// return buffer;
+
+	}
+
+	ByteBuffer getMalformedByteBuffer() {
+		// FIXME: different here
+		ByteBuffer buffer = ByteBuffer.allocate(8);
+		buffer.put((byte) -1);
+		buffer.put(getByteBuffer());
+		buffer.flip();
+		return buffer;
+
+		// TODO: how malform?
+		// return null;
+	}
+
+	ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+		return null;
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetTest.java
new file mode 100644
index 0000000..f46321e
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetTest.java
@@ -0,0 +1,59 @@
+/* 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 tests.api.java.nio.charset;
+
+/**
+ * Test charset US-ASCII.
+ */
+public class ASCCharsetTest extends AbstractCharsetTestCase {
+
+	/**
+	 * Constructor.
+	 * 
+	 */
+	public ASCCharsetTest(String arg0) {
+		super(arg0, "US-ASCII", new String[] { "ISO646-US", "ASCII", "cp367",
+				"ascii7", "ANSI_X3.4-1986", "iso-ir-6", "us", "646",
+				"iso_646.irv:1983", "csASCII", "ANSI_X3.4-1968",
+				"ISO_646.irv:1991" }, true, true); // "ibm-367"
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+	 */
+	public void testEncode_Normal() {
+		String input = "ab\u5D14\u654F";
+		byte[] output = new byte[] { 97, 98,
+				this.testingCharset.newEncoder().replacement()[0],
+				this.testingCharset.newEncoder().replacement()[0] };
+		internalTestEncode(input, output);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+	 */
+	public void testDecode_Normal() {
+		byte[] input = new byte[] { 97, 98, 63, 63 };
+		char[] output = "ab??".toCharArray();
+		internalTestDecode(input, output);
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java
new file mode 100644
index 0000000..0ebf922
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java
@@ -0,0 +1,175 @@
+/*
+ *  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 tests.api.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+
+import junit.framework.TestCase;
+
+/**
+ * Super class for concrete charset test suites.
+ */
+public abstract class AbstractCharsetTestCase extends TestCase {
+
+	// the canonical name of this charset
+	protected final String canonicalName;
+
+	// the aliases set
+	protected final String[] aliases;
+
+	// canEncode
+	protected final boolean canEncode;
+
+	// isRegistered
+	protected final boolean isRegistered;
+
+	// charset instance
+	protected Charset testingCharset;
+
+	/*
+	 * Initialize the field "testingCharset" here.
+	 * 
+	 * @see TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		super.setUp();
+		this.testingCharset = Charset.forName(this.canonicalName);
+	}
+
+	/*
+	 * @see TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	/**
+	 * Constructor for ConcreteCharsetTest.
+	 * 
+	 */
+	public AbstractCharsetTestCase(String arg0, String canonicalName,
+			String[] aliases, boolean canEncode, boolean isRegistered) {
+		super(arg0);
+		this.canonicalName = canonicalName;
+		this.canEncode = canEncode;
+		this.isRegistered = isRegistered;
+		this.aliases = aliases;
+	}
+
+	/*
+	 * Test canEncode.
+	 */
+	public void testCanEncode() {
+		assertEquals(this.canEncode, this.testingCharset.canEncode());
+	}
+
+	/*
+	 * Test isRegistered.
+	 */
+	public void testIsRegistered() {
+		assertEquals(this.isRegistered, this.testingCharset.isRegistered());
+	}
+
+	/*
+	 * Test name.
+	 */
+	public void testName() {
+		assertEquals(this.canonicalName, this.testingCharset.name());
+		// assertEquals(this.canonicalName, this.testingCharset.displayName());
+		// assertEquals(this.canonicalName,
+		// this.testingCharset.displayName(null));
+	}
+
+	/*
+	 * Test aliases.
+	 */
+	public void testAliases() {
+		for (int i = 0; i < this.aliases.length; i++) {
+			Charset c = Charset.forName(this.aliases[i]);
+			assertEquals(this.canonicalName, c.name());
+			// TODO
+			// assertTrue(this.testingCharset.aliases().contains(this.aliases[i]));
+		}
+	}
+
+	/*
+	 * Test the method encode(String) with null.
+	 */
+	public void testEncode_String_Null() {
+		try {
+			this.testingCharset.encode((String) null);
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method encode(CharBuffer) with null.
+	 */
+	public void testEncode_CharBuffer_Null() {
+		try {
+			this.testingCharset.encode((CharBuffer) null);
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test encoding.
+	 */
+	protected void internalTestEncode(String input, byte[] output) {
+		ByteBuffer bb = this.testingCharset.encode(input);
+		int i = 0;
+		bb.rewind();
+		while (bb.hasRemaining() && i < output.length) {
+			assertEquals(output[i], bb.get());
+			i++;
+		}
+		assertFalse(bb.hasRemaining());
+		assertEquals(output.length, i);
+	}
+
+	/*
+	 * Test encoding.
+	 */
+	public abstract void testEncode_Normal();
+
+	/*
+	 * Test decoding.
+	 */
+	protected void internalTestDecode(byte[] input, char[] output) {
+		CharBuffer chb = this.testingCharset.decode(ByteBuffer.wrap(input));
+		int i = 0;
+		chb.rewind();
+		while (chb.hasRemaining() && i < output.length) {
+			assertEquals(output[i], chb.get());
+			i++;
+		}
+		assertFalse(chb.hasRemaining());
+		assertEquals(output.length, i);
+	}
+
+	/*
+	 * Test decoding.
+	 */
+	public abstract void testDecode_Normal();
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
new file mode 100644
index 0000000..9cd59ea
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
@@ -0,0 +1,870 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+/**
+ * API unit test for java.nio.CharsetDecoder
+ */
+public class CharsetDecoderTest extends TestCase {
+
+    protected static final int MAX_BYTES = 3;
+
+    protected static final double AVER_BYTES = 0.5;
+
+    // default charset
+    private static final Charset MOCKCS = new CharsetEncoderTest.MockCharset(
+            "mock", new String[0]);
+
+    Charset cs = MOCKCS;
+
+    // default decoder
+    protected static CharsetDecoder decoder;
+
+    String bom = "";
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        decoder = cs.newDecoder();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    // FIXME: give up this tests
+    // /*
+    // * test default value
+    // */
+    // public void testDefaultCharsPerByte() {
+    // assertTrue(decoder.averageCharsPerByte() == AVER_BYTES);
+    // assertTrue(decoder.maxCharsPerByte() == MAX_BYTES);
+    // }
+
+    public void testDefaultValues() {
+        assertSame(cs, decoder.charset());
+        try {
+            decoder.detectedCharset();
+            fail("should unsupported");
+        } catch (UnsupportedOperationException e) {
+        }
+        try {
+            assertTrue(decoder.isCharsetDetected());
+            fail("should unsupported");
+        } catch (UnsupportedOperationException e) {
+        }
+        assertFalse(decoder.isAutoDetecting());
+        assertSame(CodingErrorAction.REPORT, decoder.malformedInputAction());
+        assertSame(CodingErrorAction.REPORT, decoder
+                .unmappableCharacterAction());
+        assertEquals(decoder.replacement(), "\ufffd");
+    }
+
+    /*
+     * test constructor
+     */
+    public void testCharsetDecoder() {
+        // default value
+        decoder = new MockCharsetDecoder(cs, (float) AVER_BYTES, MAX_BYTES);
+
+        // normal case
+        CharsetDecoder ec = new MockCharsetDecoder(cs, 1, MAX_BYTES);
+        assertSame(ec.charset(), cs);
+        assertEquals(1.0, ec.averageCharsPerByte(), 0.0);
+        assertTrue(ec.maxCharsPerByte() == MAX_BYTES);
+
+        /*
+         * ------------------------ Exceptional cases -------------------------
+         */
+        // Normal case: null charset
+        ec = new MockCharsetDecoder(null, 1, MAX_BYTES);
+        assertNull(ec.charset());
+        assertEquals(1.0, ec.averageCharsPerByte(), 0.0);
+        assertTrue(ec.maxCharsPerByte() == MAX_BYTES);
+
+        ec = new MockCharsetDecoder(new CharsetEncoderTest.MockCharset("mock",
+                new String[0]), 1, MAX_BYTES);
+
+        // Commented out since the comment is wrong since MAX_BYTES > 1
+        // // OK: average length less than max length
+        // ec = new MockCharsetDecoder(cs, MAX_BYTES, 1);
+        // assertTrue(ec.averageCharsPerByte() == MAX_BYTES);
+        // assertTrue(ec.maxCharsPerByte() == 1);
+
+        // Illegal Argument: zero length
+        try {
+            ec = new MockCharsetDecoder(cs, 0, MAX_BYTES);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+        }
+        try {
+            ec = new MockCharsetDecoder(cs, 1, 0);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+        }
+
+        // Illegal Argument: negative length
+        try {
+            ec = new MockCharsetDecoder(cs, -1, MAX_BYTES);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+        }
+        try {
+            ec = new MockCharsetDecoder(cs, 1, -1);
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    /*
+     * test onMalformedInput
+     */
+    public void testOnMalformedInput() {
+        assertSame(CodingErrorAction.REPORT, decoder.malformedInputAction());
+        try {
+            decoder.onMalformedInput(null);
+            fail("should throw null pointer exception");
+        } catch (IllegalArgumentException e) {
+        }
+        decoder.onMalformedInput(CodingErrorAction.IGNORE);
+        assertSame(CodingErrorAction.IGNORE, decoder.malformedInputAction());
+    }
+
+    /*
+     * test unmappableCharacter
+     */
+    public void testOnUnmappableCharacter() {
+        assertSame(CodingErrorAction.REPORT, decoder
+                .unmappableCharacterAction());
+        try {
+            decoder.onUnmappableCharacter(null);
+            fail("should throw null pointer exception");
+        } catch (IllegalArgumentException e) {
+        }
+        decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+        assertSame(CodingErrorAction.IGNORE, decoder
+                .unmappableCharacterAction());
+    }
+
+    /*
+     * test replaceWith
+     */
+    public void testReplaceWith() {
+        try {
+            decoder.replaceWith(null);
+            fail("should throw null pointer exception");
+        } catch (IllegalArgumentException e) {
+        }
+        try {
+            decoder.replaceWith("");
+            fail("should throw null pointer exception");
+        } catch (IllegalArgumentException e) {
+        }
+        try {
+            decoder.replaceWith("testReplaceWith");
+            fail("should throw illegal argument exception");
+        } catch (IllegalArgumentException e) {
+        }
+
+        decoder.replaceWith("a");
+        assertSame("a", decoder.replacement());
+    }
+
+    /*
+     * Class under test for CharBuffer decode(ByteBuffer)
+     */
+    public void testDecodeByteBuffer() throws CharacterCodingException {
+        implTestDecodeByteBuffer();
+    }
+
+    void implTestDecodeByteBuffer() throws CharacterCodingException {
+        // Null pointer
+        try {
+            decoder.decode(null);
+            fail("should throw null pointer exception");
+        } catch (NullPointerException e) {
+        }
+
+        // empty input buffer
+        CharBuffer out = decoder.decode(ByteBuffer.allocate(0));
+        assertCharBufferValue("", out);
+
+        // normal case
+        ByteBuffer in = getByteBuffer();
+        out = decoder.decode(in);
+        assertEquals(0, out.position());
+        assertEquals(getString().length(), out.limit());
+        assertEquals(getString().length(), out.remaining());
+        assertCharBufferValue(getString(), out);
+
+        // normal read only case
+        in = getByteBuffer().asReadOnlyBuffer();
+        out = decoder.decode(in);
+        assertEquals(out.position(), 0);
+        assertEquals(out.limit(), getString().length());
+        assertEquals(out.remaining(), getString().length());
+        assertCharBufferValue(getString(), out);
+    }
+
+    public void testDecodeByteBufferException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        CharBuffer out;
+        ByteBuffer in;
+        String replaceStr = decoder.replacement() + getString();
+
+        // MalformedException:
+        decoder.onMalformedInput(CodingErrorAction.REPORT);
+        decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        in = getMalformedByteBuffer();
+        if (in != null) {
+            try {
+                CharBuffer buffer = decoder.decode(in);
+                assertTrue(buffer.remaining() > 0);
+                fail("should throw MalformedInputException");
+            } catch (MalformedInputException e) {
+            }
+
+            decoder.reset();
+            in.rewind();
+            decoder.onMalformedInput(CodingErrorAction.IGNORE);
+            out = decoder.decode(in);
+            assertCharBufferValue(getString(), out);
+
+            decoder.reset();
+            in.rewind();
+            decoder.onMalformedInput(CodingErrorAction.REPLACE);
+            out = decoder.decode(in);
+            assertCharBufferValue(replaceStr, out);
+        }
+
+        // Unmapped Exception:
+        decoder.onMalformedInput(CodingErrorAction.REPORT);
+        decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        in = getUnmappedByteBuffer();
+        if (in != null) {
+            try {
+                decoder.decode(in);
+                fail("should throw UnmappableCharacterException");
+            } catch (UnmappableCharacterException e) {
+            }
+
+            decoder.reset();
+            in.rewind();
+            decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+            out = decoder.decode(in);
+            assertCharBufferValue(getString(), out);
+
+            decoder.reset();
+            in.rewind();
+            decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+            out = decoder.decode(in);
+            assertCharBufferValue(replaceStr, out);
+        }
+
+        // RuntimeException
+        try {
+            decoder.decode(getExceptionByteArray());
+            fail("should throw runtime exception");
+        } catch (RuntimeException e) {
+        }
+    }
+
+    /*
+     * Class under test for CoderResult decode(ByteBuffer, CharBuffer, boolean)
+     */
+    public void testDecodeByteBufferCharBuffer() {
+        implTestDecodeByteBufferCharBuffer(getByteBuffer());
+    }
+
+    public void testDecodeByteBufferCharBufferReadOnly() {
+        implTestDecodeByteBufferCharBuffer(getByteBuffer());
+    }
+
+    void implTestDecodeByteBufferCharBuffer(ByteBuffer in) {
+        CharBuffer out = CharBuffer.allocate(100);
+
+        // Null pointer
+        decoder.reset();
+        try {
+            decoder.decode(null, out, true);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+        }
+        try {
+            decoder.decode(in, null, true);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+        }
+
+        // normal case, one complete operation
+        decoder.reset();
+        in.rewind();
+        out.rewind();
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+        assertEquals(out.limit(), 100);
+        assertEquals(out.position(), getString().length());
+        assertEquals(out.remaining(), 100 - getString().length());
+        assertEquals(out.capacity(), 100);
+        assertCharBufferValue(getString(), out);
+        decoder.flush(out);
+
+        // normal case, one complete operation, but call twice, first time set
+        // endOfInput to false
+        decoder.reset();
+        in.rewind();
+        out.clear();
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+        assertEquals(out.limit(), 100);
+        assertEquals(out.position(), getString().length());
+        assertEquals(out.remaining(), 100 - getString().length());
+        assertEquals(out.capacity(), 100);
+        assertCharBufferValue(getString(), out);
+
+        decoder.reset();
+        in.rewind();
+        out.clear();
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+        in = getHeadlessByteBuffer();
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+        in.rewind();
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+        assertEquals(out.limit(), 100);
+        assertTrue(out.position() > 0);
+        assertEquals(out.remaining(), out.capacity() - out.position());
+        assertEquals(out.capacity(), 100);
+        assertCharBufferValue(getString() + getString() + getString(), out);
+
+        // overflow
+        out = CharBuffer.allocate(4);
+        decoder.reset();
+        in = getByteBuffer();
+        out.rewind();
+        assertSame(CoderResult.OVERFLOW, decoder.decode(in, out, false));
+
+        assertCharBufferValue(getString().substring(0, 4), out);
+        out = CharBuffer.allocate(100);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+        assertCharBufferValue(getString().substring(4), out);
+        in.rewind();
+        out = CharBuffer.allocate(100);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+        assertCharBufferValue(bom + getString(), out);
+    }
+
+    public void testDecodeCharBufferByteBufferUnmappedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferUnmappedException(
+                getUnmappedByteBuffer(), true);
+    }
+
+    public void testDecodeCharBufferByteIncompleteBufferUnmappedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferUnmappedException(
+                getUnmappedByteBuffer(), false);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyBufferUnmappedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferUnmappedException(
+                readOnly(getUnmappedByteBuffer()), true);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyIncompleteBufferUnmappedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferUnmappedException(
+                readOnly(getUnmappedByteBuffer()), false);
+    }
+
+    void implTestDecodeCharBufferByteBufferUnmappedException(ByteBuffer in,
+            boolean endOfInput) throws CharacterCodingException,
+            UnsupportedEncodingException {
+        if (null == in) {
+            return;
+        }
+        CharBuffer out = CharBuffer.allocate(50);
+
+        decoder.onMalformedInput(CodingErrorAction.REPORT);
+        decoder.reset();
+        decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        CoderResult result = decoder.decode(in, out, endOfInput);
+        assertTrue(result.isUnmappable());
+
+        decoder.reset();
+        out.clear();
+        in.rewind();
+        decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+        assertCharBufferValue(getString(), out);
+
+        decoder.reset();
+        out.clear();
+        in.rewind();
+        decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+        assertCharBufferValue(decoder.replacement() + getString(), out);
+    }
+
+    public void testDecodeCharBufferByteBufferMalformedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferMalformedException(
+                getMalformedByteBuffer(), true);
+    }
+
+    public void testDecodeCharBufferByteIncompleteBufferMalformedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+
+        implTestDecodeCharBufferByteBufferMalformedException(
+                getMalformedByteBuffer(), false);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyBufferMalformedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferMalformedException(
+                readOnly(getMalformedByteBuffer()), true);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyIncompleteBufferMalformedException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferMalformedException(
+                readOnly(getMalformedByteBuffer()), false);
+    }
+
+    void implTestDecodeCharBufferByteBufferMalformedException(ByteBuffer in,
+            boolean endOfInput) throws CharacterCodingException,
+            UnsupportedEncodingException {
+        if (null == in) {
+            return;
+        }
+        CharBuffer out = CharBuffer.allocate(getString().length() * 3);
+        decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+        decoder.reset();
+        decoder.onMalformedInput(CodingErrorAction.REPORT);
+        CoderResult result = decoder.decode(in, out, endOfInput);
+        assertTrue(result.isMalformed());
+
+        decoder.reset();
+        out.clear();
+        in.rewind();
+        decoder.onMalformedInput(CodingErrorAction.IGNORE);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+        assertCharBufferValue(getString(), out);
+
+        decoder.reset();
+        out.clear();
+        in.rewind();
+        decoder.onMalformedInput(CodingErrorAction.REPLACE);
+        assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+        assertCharBufferValue(decoder.replacement() + getString(), out);
+    }
+
+    public void testDecodeCharBufferByteBufferException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferException(getExceptionByteArray(),
+                true);
+    }
+
+    public void testDecodeCharBufferByteIncompleteBufferException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferException(getExceptionByteArray(),
+                false);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyBufferException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferException(
+                readOnly(getExceptionByteArray()), true);
+    }
+
+    public void testDecodeCharBufferByteReadOnlyIncompleteBufferException()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        implTestDecodeCharBufferByteBufferException(
+                readOnly(getExceptionByteArray()), false);
+    }
+
+    void implTestDecodeCharBufferByteBufferException(ByteBuffer in,
+            boolean endOfInput) throws CharacterCodingException,
+            UnsupportedEncodingException {
+        CharBuffer out = CharBuffer.allocate(50);
+        decoder.reset();
+        try {
+            decoder.decode(in, out, endOfInput);
+            fail("should throw runtime exception");
+        } catch (RuntimeException e) {
+        }
+    }
+
+    private ByteBuffer readOnly(ByteBuffer b) {
+        if (null == b) {
+            return null;
+        }
+        return b.asReadOnlyBuffer();
+    }
+
+    protected String getString() {
+        return " buffer";
+    }
+
+    protected ByteBuffer getByteBuffer() {
+        return ByteBuffer.wrap(new byte[] { 32, 98, 117, 102, 102, 101, 114 });
+    }
+
+    protected ByteBuffer getHeadlessByteBuffer() {
+        return getByteBuffer();
+    }
+
+    ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+        // "runtime"
+        return ByteBuffer
+                .wrap(new byte[] { 114, 117, 110, 116, 105, 109, 101 });
+    }
+
+    ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+        // "unmap buffer"
+        byte[] ba = new byte[] { 117, 110, 109, 97, 112, 32, 98, 117, 102, 102,
+                101, 114 };
+        return ByteBuffer.wrap(ba);
+    }
+
+    ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+        // "malform buffer"
+        byte[] ba = new byte[] { 109, 97, 108, 102, 111, 114, 109, 32, 98, 117,
+                102, 102, 101, 114 };
+        return ByteBuffer.wrap(ba);
+    }
+
+    private void assertCharBufferValue(String expected, CharBuffer out) {
+        if (out.position() != 0) {
+            out.flip();
+        }
+        assertEquals(expected, new String(out.array(), out.arrayOffset(), out
+                .arrayOffset() + out.limit()));
+    }
+
+    /*
+     * test flush
+     */
+    public void testFlush() throws CharacterCodingException {
+        CharBuffer out = CharBuffer.allocate(10);
+        ByteBuffer in = ByteBuffer.wrap(new byte[] { 12, 12 });
+        decoder.decode(in, out, true);
+        assertSame(CoderResult.UNDERFLOW, decoder.flush(out));
+
+        decoder.reset();
+        decoder.decode((ByteBuffer) in.rewind(), (CharBuffer) out.rewind(),
+                true);
+        assertSame(CoderResult.UNDERFLOW, decoder
+                .flush(CharBuffer.allocate(10)));
+    }
+
+    /*
+     * ---------------------------------- methods to test illegal state
+     * -----------------------------------
+     */
+    // Normal case: just after reset, and it also means reset can be done
+    // anywhere
+    public void testResetIllegalState() throws CharacterCodingException {
+        decoder.reset();
+        decoder.decode(getByteBuffer());
+        decoder.reset();
+        decoder.decode(getByteBuffer(), CharBuffer.allocate(3), false);
+        decoder.reset();
+        decoder.decode(getByteBuffer(), CharBuffer.allocate(3), true);
+        decoder.reset();
+    }
+
+    public void testFlushIllegalState() throws CharacterCodingException {
+        ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+        CharBuffer out = CharBuffer.allocate(5);
+        // Normal case: after decode with endOfInput is true
+        decoder.reset();
+        decoder.decode(in, out, true);
+        out.rewind();
+        CoderResult result = decoder.flush(out);
+        assertSame(result, CoderResult.UNDERFLOW);
+
+        // Illegal state: flush twice
+        try {
+            decoder.flush(out);
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+        }
+
+        // Illegal state: flush after decode with endOfInput is false
+        decoder.reset();
+        decoder.decode(in, out, false);
+        try {
+            decoder.flush(out);
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException e) {
+        }
+    }
+    
+    // test illegal states for decode facade
+    public void testDecodeFacadeIllegalState() throws CharacterCodingException {
+        // decode facade can be execute in anywhere
+        ByteBuffer in = getByteBuffer();
+
+        // Normal case: just created
+        decoder.decode(in);
+        in.rewind();
+
+        // Normal case: just after decode facade
+        decoder.decode(in);
+        in.rewind();
+
+        // Normal case: just after decode with that endOfInput is true
+        decoder.reset();
+        decoder.decode(getByteBuffer(), CharBuffer.allocate(30), true);
+        decoder.decode(in);
+        in.rewind();
+
+        // Normal case:just after decode with that endOfInput is false
+        decoder.reset();
+        decoder.decode(getByteBuffer(), CharBuffer.allocate(30), false);
+        decoder.decode(in);
+        in.rewind();
+
+        // Normal case: just after flush
+        decoder.reset();
+        decoder.decode(getByteBuffer(), CharBuffer.allocate(30), true);
+        decoder.flush(CharBuffer.allocate(10));
+        decoder.decode(in);
+        in.rewind();
+    }
+
+    // test illegal states for two decode method with endOfInput is true
+    public void testDecodeTrueIllegalState() throws CharacterCodingException {
+        ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+        CharBuffer out = CharBuffer.allocate(100);
+        // Normal case: just created
+        decoder.decode(in, out, true);
+        in.rewind();
+        out.rewind();
+
+        // Normal case: just after decode with that endOfInput is true
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), true);
+        in.rewind();
+        decoder.decode(in, out, true);
+        in.rewind();
+        out.rewind();
+
+        // Normal case:just after decode with that endOfInput is false
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), false);
+        in.rewind();
+        decoder.decode(in, out, true);
+        in.rewind();
+        out.rewind();
+
+        // Illegal state: just after flush
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), true);
+        decoder.flush(CharBuffer.allocate(10));
+        in.rewind();
+        try {
+            decoder.decode(in, out, true);
+            fail("should illegal state");
+        } catch (IllegalStateException e) {
+        }
+        in.rewind();
+        out.rewind();
+
+    }
+
+    // test illegal states for two decode method with endOfInput is false
+    public void testDecodeFalseIllegalState() throws CharacterCodingException {
+        ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+        CharBuffer out = CharBuffer.allocate(5);
+        // Normal case: just created
+        decoder.decode(in, out, false);
+        in.rewind();
+        out.rewind();
+
+        // Illegal state: just after decode facade
+        decoder.reset();
+        decoder.decode(in);
+        in.rewind();
+        try {
+            decoder.decode(in, out, false);
+            fail("should illegal state");
+        } catch (IllegalStateException e) {
+        }
+        in.rewind();
+        out.rewind();
+
+        // Illegal state: just after decode with that endOfInput is true
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), true);
+        in.rewind();
+        try {
+            decoder.decode(in, out, false);
+            fail("should illegal state");
+        } catch (IllegalStateException e) {
+        }
+        in.rewind();
+        out.rewind();
+
+        // Normal case:just after decode with that endOfInput is false
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), false);
+        in.rewind();
+        decoder.decode(in, out, false);
+        in.rewind();
+        out.rewind();
+
+        // Illegal state: just after flush
+        decoder.reset();
+        decoder.decode(in, CharBuffer.allocate(30), true);
+        in.rewind();
+        decoder.flush(CharBuffer.allocate(10));
+        try {
+            decoder.decode(in, out, false);
+            fail("should illegal state");
+        } catch (IllegalStateException e) {
+        }
+    }
+
+    /*
+     * --------------------------------- illegal state test end
+     * ---------------------------------
+     */
+
+    public void testImplFlush() {
+        decoder = new MockCharsetDecoder(cs, 1, 3);
+        assertEquals(CoderResult.UNDERFLOW, ((MockCharsetDecoder) decoder)
+                .pubImplFlush(null));
+    }
+
+    public void testImplOnMalformedInput() {
+        decoder = new MockCharsetDecoder(cs, 1, 3);
+        assertEquals(CoderResult.UNDERFLOW, ((MockCharsetDecoder) decoder)
+                .pubImplFlush(null));
+
+    }
+
+    public void testImplOnUnmappableCharacter() {
+        decoder = new MockCharsetDecoder(cs, 1, 3);
+        ((MockCharsetDecoder) decoder).pubImplOnUnmappableCharacter(null);
+    }
+
+    public void testImplReplaceWith() {
+        decoder = new MockCharsetDecoder(cs, 1, 3);
+        ((MockCharsetDecoder) decoder).pubImplReplaceWith(null);
+    }
+
+    public void testImplReset() {
+        decoder = new MockCharsetDecoder(cs, 1, 3);
+        ((MockCharsetDecoder) decoder).pubImplReset();
+    }
+
+    /*
+     * mock decoder
+     */
+    public static class MockCharsetDecoder extends CharsetDecoder {
+        public MockCharsetDecoder(Charset cs, float ave, float max) {
+            super(cs, ave, max);
+        }
+
+        protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+            int inPosition = in.position();
+            byte[] input = new byte[in.remaining()];
+            in.get(input);
+            String result;
+            try {
+                result = new String(input, "UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                throw new AssertionError(e);
+            }
+            if (result.startsWith("malform")) {
+                // reset the cursor to the error position
+                in.position(inPosition);
+                // set the error length
+                return CoderResult.malformedForLength("malform".length());
+            } else if (result.startsWith("unmap")) {
+                // reset the cursor to the error position
+                in.position(inPosition);
+                // set the error length
+                return CoderResult.unmappableForLength("unmap".length());
+            } else if (result.startsWith("runtime")) {
+                // reset the cursor to the error position
+                in.position(0);
+                // set the error length
+                throw new RuntimeException("runtime");
+            }
+            int inLeft = input.length;
+            int outLeft = out.remaining();
+            CoderResult r = CoderResult.UNDERFLOW;
+            int length = inLeft;
+            if (outLeft < inLeft) {
+                r = CoderResult.OVERFLOW;
+                length = outLeft;
+                in.position(inPosition + outLeft);
+            }
+            for (int i = 0; i < length; i++) {
+                out.put((char) input[i]);
+            }
+            return r;
+        }
+
+        protected CoderResult implFlush(CharBuffer out) {
+            CoderResult result = super.implFlush(out);
+            if (out.remaining() >= 5) {
+                // TODO
+                // out.put("flush");
+                result = CoderResult.UNDERFLOW;
+            } else {
+                // out.put("flush", 0, out.remaining());
+                result = CoderResult.OVERFLOW;
+            }
+            return result;
+        }
+
+        public CoderResult pubImplFlush(CharBuffer out) {
+            return super.implFlush(out);
+        }
+
+        public void pubImplOnMalformedInput(CodingErrorAction newAction) {
+            super.implOnMalformedInput(newAction);
+        }
+
+        public void pubImplOnUnmappableCharacter(CodingErrorAction newAction) {
+            super.implOnUnmappableCharacter(newAction);
+        }
+
+        public void pubImplReplaceWith(String newReplacement) {
+            super.implReplaceWith(newReplacement);
+        }
+
+        public void pubImplReset() {
+            super.implReset();
+        }
+
+    }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
new file mode 100644
index 0000000..ef219be
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
@@ -0,0 +1,1137 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+/**
+ * API unit test for java.nio.charset.CharsetEncoder
+ */
+public class CharsetEncoderTest extends TestCase {
+
+	static final int MAX_BYTES = 3;
+
+	static final float AVER_BYTES = 0.5f;
+
+	// charset for mock class
+	private static final Charset MOCKCS = new MockCharset("CharsetEncoderTest_mock", new String[0]);
+
+	Charset cs = MOCKCS;
+
+	// default encoder
+	CharsetEncoder encoder;
+
+	// default for Charset abstract class
+	byte[] defaultReplacement = new byte[] { 63 };
+
+	// specific for Charset implementation subclass
+	byte[] specifiedReplacement = new byte[] { 63 };
+
+	static final String unistr = " buffer";// \u8000\u8001\u00a5\u3000\r\n";
+
+	byte[] unibytes = new byte[] { 32, 98, 117, 102, 102, 101, 114 };
+
+	byte[] unibytesWithRep = null;
+
+	byte[] surrogate = new byte[0];
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		encoder = cs.newEncoder();
+		if (null == unibytesWithRep) {
+			byte[] replacement = encoder.replacement();
+			unibytesWithRep = new byte[replacement.length + unibytes.length];
+			System.arraycopy(replacement, 0, unibytesWithRep, 0,
+					replacement.length);
+			System.arraycopy(unibytes, 0, unibytesWithRep, replacement.length,
+					unibytes.length);
+		}
+	}
+
+	/*
+	 * @see TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	public void testSpecificDefaultValue() {
+		assertTrue(encoder.averageBytesPerChar() == AVER_BYTES);
+		assertTrue(encoder.maxBytesPerChar() == MAX_BYTES);
+	}
+
+	public void testDefaultValue() {
+		assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction());
+		assertEquals(CodingErrorAction.REPORT, encoder.unmappableCharacterAction());
+		assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE));
+		assertSame(encoder, encoder.onUnmappableCharacter(CodingErrorAction.IGNORE));
+		if (encoder instanceof MockCharsetEncoder) {
+			assertTrue(Arrays.equals(encoder.replacement(), defaultReplacement));
+		} else {
+			assertTrue(Arrays.equals(encoder.replacement(), specifiedReplacement));
+		}
+
+	}
+
+	/*
+	 * Class under test for constructor CharsetEncoder(Charset, float, float)
+	 */
+	public void testCharsetEncoderCharsetfloatfloat() {
+		// default value
+		encoder = new MockCharsetEncoder(cs, (float) AVER_BYTES, MAX_BYTES);
+		assertSame(encoder.charset(), cs);
+		assertTrue(encoder.averageBytesPerChar() == AVER_BYTES);
+		assertTrue(encoder.maxBytesPerChar() == MAX_BYTES);
+		assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction());
+		assertEquals(CodingErrorAction.REPORT, encoder
+				.unmappableCharacterAction());
+		assertEquals(new String(encoder.replacement()), new String(
+				defaultReplacement));
+		assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE));
+		assertSame(encoder, encoder
+				.onUnmappableCharacter(CodingErrorAction.IGNORE));
+
+		// normal case
+		CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES);
+		assertSame(ec.charset(), cs);
+		assertEquals(1.0, ec.averageBytesPerChar(), 0);
+		assertTrue(ec.maxBytesPerChar() == MAX_BYTES);
+
+		/*
+		 * ------------------------ Exceptional cases -------------------------
+		 */
+		// NullPointerException: null charset
+		try {
+			ec = new MockCharsetEncoder(null, 1, MAX_BYTES);
+			fail("should throw null pointer exception");
+		} catch (NullPointerException e) {
+		}
+
+		ec = new MockCharsetEncoder(new MockCharset("mock", new String[0]), 1,
+				MAX_BYTES);
+
+                // Commented out since the comment is wrong since MAX_BYTES > 1
+		// // OK: average length less than max length
+		// ec = new MockCharsetEncoder(cs, MAX_BYTES, 1);
+		// assertTrue(ec.averageBytesPerChar() == MAX_BYTES);
+		// assertTrue(ec.maxBytesPerChar() == 1);
+
+		// Illegal Argument: zero length
+		try {
+			ec = new MockCharsetEncoder(cs, 0, MAX_BYTES);
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+		try {
+			ec = new MockCharsetEncoder(cs, 1, 0);
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+
+		// Illegal Argument: negative length
+		try {
+			ec = new MockCharsetEncoder(cs, -1, MAX_BYTES);
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+		try {
+			ec = new MockCharsetEncoder(cs, 1, -1);
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+	}
+
+	/*
+	 * Class under test for constructor CharsetEncoder(Charset, float, float,
+	 * byte[])
+	 */
+	public void testCharsetEncoderCharsetfloatfloatbyteArray() {
+		byte[] ba = getLegalByteArray();
+		// normal case
+		CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, ba);
+		assertSame(ec.charset(), cs);
+		assertEquals(1.0, ec.averageBytesPerChar(), 0.0);
+		assertTrue(ec.maxBytesPerChar() == MAX_BYTES);
+		assertSame(ba, ec.replacement());
+
+		/*
+		 * ------------------------ Exceptional cases -------------------------
+		 */
+		// NullPointerException: null charset
+		try {
+			ec = new MockCharsetEncoder(null, 1, MAX_BYTES, ba);
+			fail("should throw null pointer exception");
+		} catch (NullPointerException e) {
+		}
+
+		// Illegal Argument: null byte array
+		try {
+			ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, null);
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+		// Illegal Argument: empty byte array
+		try {
+			ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[0]);
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+		// Illegal Argument: byte array is longer than max length
+		try {
+			ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[] { 1, 2,
+					MAX_BYTES, 4 });
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+
+                // Commented out since the comment is wrong since MAX_BYTES > 1
+                // This test throws IllegalArgumentException on Harmony and RI
+		// // OK: average length less than max length
+		// ec = new MockCharsetEncoder(cs, MAX_BYTES, ba.length, ba);
+		// assertTrue(ec.averageBytesPerChar() == MAX_BYTES);
+		// assertTrue(ec.maxBytesPerChar() == ba.length);
+
+		// Illegal Argument: zero length
+		try {
+			ec = new MockCharsetEncoder(cs, 0, MAX_BYTES, ba);
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+		try {
+			ec = new MockCharsetEncoder(cs, 1, 0, ba);
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+
+		// Illegal Argument: negative length
+		try {
+			ec = new MockCharsetEncoder(cs, -1, MAX_BYTES, ba);
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+		try {
+			ec = new MockCharsetEncoder(cs, 1, -1, ba);
+			fail("should throw IllegalArgumentException");
+		} catch (IllegalArgumentException e) {
+		}
+	}
+
+	/*
+	 * Class under test for boolean canEncode(char)
+	 */
+	public void testCanEncodechar() throws CharacterCodingException {
+		// for non-mapped char
+		assertTrue(encoder.canEncode('\uc2c0'));
+		// surrogate char for unicode
+		// 1st byte: d800-dbff
+		// 2nd byte: dc00-dfff
+		assertTrue(encoder.canEncode('\ud800'));
+		// valid surrogate pair
+		assertTrue(encoder.canEncode('\udc00'));
+	}
+
+	/*-----------------------------------------
+	 * Class under test for illegal state case
+	 * methods which can change internal states are two encode, flush, two canEncode, reset
+	 * -----------------------------------------
+	 */
+
+	// Normal case: just after reset, and it also means reset can be done
+	// anywhere
+	public void testResetIllegalState() throws CharacterCodingException {
+		assertSame(encoder, encoder.reset());
+		encoder.canEncode('\ud901');
+		assertSame(encoder, encoder.reset());
+		encoder.canEncode("\ud901\udc00");
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("aaa"));
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("aaa"), ByteBuffer.allocate(3), false);
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("aaa"), ByteBuffer.allocate(3), true);
+		assertSame(encoder, encoder.reset());
+	}
+
+	public void testFlushIllegalState() throws CharacterCodingException {
+		CharBuffer in = CharBuffer.wrap("aaa");
+		ByteBuffer out = ByteBuffer.allocate(5);
+
+		// Normal case: after encode with endOfInput is true
+		assertSame(encoder, encoder.reset());
+		encoder.encode(in, out, true);
+		out.rewind();
+		CoderResult result = encoder.flush(out);
+
+		// Illegal state: flush twice
+		try {
+			encoder.flush(out);
+			fail("should throw IllegalStateException");
+		} catch (IllegalStateException e) {
+		    // Expected
+		}
+
+		// Illegal state: flush after encode with endOfInput is false
+		assertSame(encoder, encoder.reset());
+		encoder.encode(in, out, false);
+		try {
+			encoder.flush(out);
+			fail("should throw IllegalStateException");
+		} catch (IllegalStateException e) {
+		    // Expected
+		}
+	}
+
+	public void testFlushAfterConstructing() {
+		ByteBuffer out = ByteBuffer.allocate(5);
+
+		//Illegal state: flush after instance created
+		try {
+			encoder.flush(out);
+			fail("should throw IllegalStateException");
+		} catch (IllegalStateException e) {
+			// Expected
+		}
+
+	}
+
+	// test illegal states for encode facade
+	public void testEncodeFacadeIllegalState() throws CharacterCodingException {
+		// encode facade can be execute in anywhere
+		CharBuffer in = CharBuffer.wrap("aaa");
+		// Normal case: just created
+		encoder.encode(in);
+		in.rewind();
+
+		// Normal case: just after encode facade
+		encoder.encode(in);
+		in.rewind();
+
+		// Normal case: just after canEncode
+		assertSame(encoder, encoder.reset());
+		encoder.canEncode("\ud902\udc00");
+		encoder.encode(in);
+		in.rewind();
+		assertSame(encoder, encoder.reset());
+		encoder.canEncode('\ud902');
+		encoder.encode(in);
+		in.rewind();
+
+		// Normal case: just after encode with that endOfInput is true
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+				ByteBuffer.allocate(30), true);
+		encoder.encode(in);
+		in.rewind();
+
+		// Normal case:just after encode with that endOfInput is false
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+				ByteBuffer.allocate(30), false);
+		encoder.encode(in);
+		in.rewind();
+
+		// Normal case: just after flush
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+				ByteBuffer.allocate(30), true);
+		encoder.flush(ByteBuffer.allocate(10));
+		encoder.encode(in);
+		in.rewind();
+	}
+
+	// test illegal states for two encode method with endOfInput is true
+	public void testEncodeTrueIllegalState() throws CharacterCodingException {
+		CharBuffer in = CharBuffer.wrap("aaa");
+		ByteBuffer out = ByteBuffer.allocate(5);
+		// Normal case: just created
+		encoder.encode(in, out, true);
+		in.rewind();
+		out.rewind();
+
+		in.rewind();
+		out.rewind();
+
+		// Normal case: just after encode with that endOfInput is true
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+				ByteBuffer.allocate(30), true);
+		encoder.encode(in, out, true);
+		in.rewind();
+		out.rewind();
+
+		// Normal case:just after encode with that endOfInput is false
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+				ByteBuffer.allocate(30), false);
+		encoder.encode(in, out, true);
+		in.rewind();
+		out.rewind();
+
+		// Illegal state: just after flush
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+				ByteBuffer.allocate(30), true);
+		encoder.flush(ByteBuffer.allocate(10));
+		try {
+			encoder.encode(in, out, true);
+			fail("should illegal state");
+		} catch (IllegalStateException e) {
+		}
+
+		// Normal case: after canEncode
+		assertSame(encoder, encoder.reset());
+		encoder.canEncode("\ud906\udc00");
+		encoder.encode(in, out, true);
+		in.rewind();
+		out.rewind();
+		assertSame(encoder, encoder.reset());
+		encoder.canEncode('\ud905');
+		encoder.encode(in, out, true);
+	}
+
+	// test illegal states for two encode method with endOfInput is false
+	public void testEncodeFalseIllegalState() throws CharacterCodingException {
+		CharBuffer in = CharBuffer.wrap("aaa");
+		ByteBuffer out = ByteBuffer.allocate(5);
+		// Normal case: just created
+		encoder.encode(in, out, false);
+		in.rewind();
+		out.rewind();
+
+		// Illegal state: just after encode facade
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState1"));
+		try {
+			encoder.encode(in, out, false);
+			fail("should illegal state");
+		} catch (IllegalStateException e) {
+		}
+
+		// Illegal state: just after encode with that endOfInput is true
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+				ByteBuffer.allocate(30), true);
+		try {
+			encoder.encode(in, out, false);
+			fail("should illegal state");
+		} catch (IllegalStateException e) {
+		}
+
+		// Normal case:just after encode with that endOfInput is false
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+				ByteBuffer.allocate(30), false);
+		encoder.encode(in, out, false);
+		in.rewind();
+		out.rewind();
+
+		// Illegal state: just after flush
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+				ByteBuffer.allocate(30), true);
+		encoder.flush(ByteBuffer.allocate(10));
+		try {
+			encoder.encode(in, out, false);
+			fail("should illegal state");
+		} catch (IllegalStateException e) {
+		}
+
+		// Normal case: after canEncode
+		assertSame(encoder, encoder.reset());
+		encoder.canEncode("\ud906\udc00");
+		encoder.encode(in, out, false);
+		in.rewind();
+		out.rewind();
+		assertSame(encoder, encoder.reset());
+		encoder.canEncode('\ud905');
+		encoder.encode(in, out, false);
+	}
+
+	// test illegal states for two canEncode methods
+	public void testCanEncodeIllegalState() throws CharacterCodingException {
+		// Normal case: just created
+		encoder.canEncode("\ud900\udc00");
+		encoder.canEncode('\ud900');
+
+		// Illegal state: just after encode with that endOfInput is true
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+				ByteBuffer.allocate(30), true);
+		try {
+			encoder.canEncode("\ud903\udc00");
+			fail("should throw illegal state exception");
+		} catch (IllegalStateException e) {
+		}
+
+		// Illegal state:just after encode with that endOfInput is false
+		assertSame(encoder, encoder.reset());
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+				ByteBuffer.allocate(30), false);
+		try {
+			encoder.canEncode("\ud904\udc00");
+			fail("should throw illegal state exception");
+		} catch (IllegalStateException e) {
+		}
+
+		// Normal case: just after flush
+		encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+				ByteBuffer.allocate(30), true);
+		encoder.flush(ByteBuffer.allocate(10));
+		encoder.canEncode("\ud905\udc00");
+		encoder.canEncode('\ud906');
+
+		// Normal case: after reset again
+		assertSame(encoder, encoder.reset());
+		encoder.canEncode("\ud906\udc00");
+		encoder.canEncode('\ud905');
+	}
+
+	/*
+	 * --------------------------------- illegal state test end
+	 * ---------------------------------
+	 */
+
+	/*
+	 * Class under test for boolean canEncode(CharSequence)
+	 */
+	public void testCanEncodeCharSequence() {
+		// for non-mapped char
+		assertTrue(encoder.canEncode("\uc2c0"));
+		// surrogate char for unicode
+		// 1st byte: d800-dbff
+		// 2nd byte: dc00-dfff
+		// valid surrogate pair
+		assertTrue(encoder.canEncode("\ud800\udc00"));
+		// invalid surrogate pair
+		assertTrue(encoder.canEncode("\ud800\udb00"));
+	}
+
+    public void test_canEncode_char_ICUBug() {
+        // The RI doesn't allow this, but icu4c does.
+        assertTrue(encoder.canEncode('\ud800'));
+    }
+
+    public void test_canEncode_CharSequence_ICUBug() {
+        // The RI doesn't allow this, but icu4c does.
+        assertTrue(encoder.canEncode("\ud800"));
+    }
+
+    public void test_canEncode_empty() throws Exception {
+        assertTrue(encoder.canEncode(""));
+    }
+
+    public void test_canEncode_null() throws Exception {
+        try {
+            encoder.canEncode(null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+	/*
+	 * Class under test for Charset charset()
+	 */
+	public void testCharset() {
+		try {
+			encoder = new MockCharsetEncoder(Charset.forName("gbk"), 1,
+					MAX_BYTES);
+			// assertSame(encoder.charset(), Charset.forName("gbk"));
+		} catch (UnsupportedCharsetException e) {
+			System.err
+					.println("Don't support GBK encoding, ignore current test");
+		}
+	}
+
+	/*
+	 * Class under test for ByteBuffer encode(CharBuffer)
+	 */
+	public void testEncodeCharBuffer() throws CharacterCodingException {
+		// Null pointer
+		try {
+			encoder.encode(null);
+			fail("should throw null pointer exception");
+		} catch (NullPointerException e) {
+		}
+
+		// empty input buffer
+		ByteBuffer out = encoder.encode(CharBuffer.wrap(""));
+		assertEquals(out.position(), 0);
+		assertByteArray(out, new byte[0]);
+		// assertByteArray(out, surrogate);
+
+		// normal case
+		out = encoder.encode(CharBuffer.wrap(unistr));
+		assertEquals(out.position(), 0);
+		assertByteArray(out, addSurrogate(unibytes));
+
+        // Regression test for harmony-3378
+        Charset cs = Charset.forName("UTF-8");
+        CharsetEncoder encoder = cs.newEncoder();
+        encoder.onMalformedInput(CodingErrorAction.REPLACE);
+        encoder = encoder.replaceWith(new byte[] { (byte) 0xef, (byte) 0xbf,
+                (byte) 0xbd, });
+        CharBuffer in = CharBuffer.wrap("\ud800");
+        out = encoder.encode(in);
+        assertNotNull(out);
+	}
+
+	private byte[] addSurrogate(byte[] expected) {
+		if (surrogate.length > 0) {
+			byte[] temp = new byte[surrogate.length + expected.length];
+			System.arraycopy(surrogate, 0, temp, 0, surrogate.length);
+			System.arraycopy(expected, 0, temp, surrogate.length,
+					expected.length);
+			expected = temp;
+		}
+		return expected;
+	}
+
+	/**
+	 * @return
+	 */
+	protected byte[] getEmptyByteArray() {
+		return new byte[0];
+	}
+
+	CharBuffer getMalformedCharBuffer() {
+		return CharBuffer.wrap("malform buffer");
+	}
+
+	CharBuffer getUnmapCharBuffer() {
+		return CharBuffer.wrap("unmap buffer");
+	}
+
+	CharBuffer getExceptionCharBuffer() {
+		return CharBuffer.wrap("runtime buffer");
+	}
+
+	public void testEncodeCharBufferException() throws CharacterCodingException {
+		ByteBuffer out;
+		CharBuffer in;
+		// MalformedException:
+		in = getMalformedCharBuffer();
+		encoder.onMalformedInput(CodingErrorAction.REPORT);
+		encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+		if (in != null) {
+			try {
+                // regression test for Harmony-1379
+				encoder.encode(in);
+				fail("should throw MalformedInputException");
+			} catch (MalformedInputException e) {
+			}
+
+			encoder.reset();
+			in.rewind();
+			encoder.onMalformedInput(CodingErrorAction.IGNORE);
+			out = encoder.encode(in);
+			assertByteArray(out, addSurrogate(unibytes));
+
+			encoder.reset();
+			in.rewind();
+			encoder.onMalformedInput(CodingErrorAction.REPLACE);
+			out = encoder.encode(in);
+			assertByteArray(out, addSurrogate(unibytesWithRep));
+		}
+
+		// Unmapped Exception:
+		in = getUnmapCharBuffer();
+		encoder.onMalformedInput(CodingErrorAction.REPORT);
+		encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+		if (in != null) {
+			encoder.reset();
+			try {
+				encoder.encode(in);
+				fail("should throw UnmappableCharacterException");
+			} catch (UnmappableCharacterException e) {
+			}
+
+			encoder.reset();
+			in.rewind();
+			encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+			out = encoder.encode(in);
+			assertByteArray(out, unibytes);
+
+			encoder.reset();
+			in.rewind();
+			encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+			out = encoder.encode(in);
+			assertByteArray(out, unibytesWithRep);
+		}
+
+		// RuntimeException
+		try {
+			encoder.encode(getExceptionCharBuffer());
+			fail("should throw runtime exception");
+		} catch (RuntimeException e) {
+		}
+	}
+
+	/*
+	 * utility method, extract given bytebuffer to a string and compare with
+	 * give string
+	 */
+	void assertByteArray(ByteBuffer out, byte[] expected) {
+		out = out.duplicate();
+		if (out.position() != 0) {
+			out.flip();
+		}
+		byte[] ba = new byte[out.limit() - out.position()];
+		out.get(ba);
+		// byte[] ba = out.array();
+		assertTrue(Arrays.equals(ba, expected));
+	}
+
+	/*
+	 * Class under test for CoderResult encode(CharBuffer, ByteBuffer, boolean)
+	 */
+	public void testEncodeCharBufferByteBufferboolean()
+			throws CharacterCodingException {
+		ByteBuffer out = ByteBuffer.allocate(200);
+		CharBuffer in = CharBuffer.wrap(unistr);
+		// Null pointer
+		try {
+			encoder.encode(null, out, true);
+			fail("should throw null pointer exception");
+		} catch (NullPointerException e) {
+		}
+		try {
+			encoder.encode(in, null, true);
+			fail("should throw null pointer exception");
+		} catch (NullPointerException e) {
+		}
+
+		// normal case, one complete operation
+		assertSame(encoder, encoder.reset());
+		in.rewind();
+		out.rewind();
+		assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+		assertEquals(out.limit(), 200);
+		assertTrue(out.position() > 0);
+		assertTrue(out.remaining() > 0);
+		assertEquals(out.capacity(), 200);
+		assertByteArray(out, addSurrogate(unibytes));
+		in.rewind();
+
+		encoder.flush(out);
+
+		// normal case, one complete operation, but call twice, first time set
+		// endOfInput to false
+		assertSame(encoder, encoder.reset());
+		in.rewind();
+		out = ByteBuffer.allocate(200);
+		assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
+		assertEquals(out.limit(), 200);
+		assertTrue(out.position() > 0);
+		assertTrue(out.remaining() > 0);
+		assertEquals(out.capacity(), 200);
+		assertByteArray(out, addSurrogate(unibytes));
+
+		in.rewind();
+		assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
+		in.rewind();
+		assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+		assertEquals(out.limit(), 200);
+		assertTrue(out.position() > 0);
+		assertTrue(out.remaining() > 0);
+		assertEquals(out.capacity(), 200);
+
+		assertByteArray(out, addSurrogate(duplicateByteArray(unibytes, 3)));
+
+		// overflow
+		out = ByteBuffer.allocate(4);
+		assertSame(encoder, encoder.reset());
+		in.rewind();
+		out.rewind();
+		assertSame(CoderResult.OVERFLOW, encoder.encode(in, out, true));
+		assertEquals(out.limit(), 4);
+		assertEquals(out.position(), 4);
+		assertEquals(out.remaining(), 0);
+		assertEquals(out.capacity(), 4);
+		ByteBuffer temp = ByteBuffer.allocate(200);
+		out.flip();
+		temp.put(out);
+		out = temp;
+		assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+		assertEquals(out.limit(), 200);
+		assertTrue(out.position() > 0);
+		assertTrue(out.remaining() > 0);
+		assertEquals(out.capacity(), 200);
+		assertByteArray(out, addSurrogate(unibytes));
+
+		assertSame(encoder, encoder.reset());
+		in.rewind();
+		out = ByteBuffer.allocate(4);
+		assertSame(CoderResult.OVERFLOW, encoder.encode(in, out, false));
+		assertEquals(out.limit(), 4);
+		assertEquals(out.position(), 4);
+		assertEquals(out.remaining(), 0);
+		assertEquals(out.capacity(), 4);
+		temp = ByteBuffer.allocate(200);
+		out.flip();
+		temp.put(out);
+		out = temp;
+		assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
+		assertEquals(out.limit(), 200);
+		assertTrue(out.position() > 0);
+		assertTrue(out.remaining() > 0);
+		assertEquals(out.capacity(), 200);
+		assertByteArray(out, addSurrogate(unibytes));
+	}
+
+	void printByteBuffer(ByteBuffer buffer) {
+		System.out.println("print buffer");
+		if (buffer.position() != 0) {
+			buffer.flip();
+		}
+		byte[] ba = buffer.array();
+		for (int i = 0; i < ba.length; i++) {
+			System.out.println(Integer.toHexString(ba[i]));
+		}
+	}
+
+	public void testEncodeCharBufferByteBufferbooleanExceptionFalse()
+			throws CharacterCodingException {
+		implTestEncodeCharBufferByteBufferbooleanException(false);
+	}
+
+	public void testEncodeCharBufferByteBufferbooleanExceptionTrue()
+			throws CharacterCodingException {
+		implTestEncodeCharBufferByteBufferbooleanException(true);
+	}
+
+	private byte[] duplicateByteArray(byte[] ba, int times) {
+		byte[] result = new byte[ba.length * times];
+		for (int i = 0; i < times; i++) {
+			System.arraycopy(ba, 0, result, i * ba.length, ba.length);
+		}
+		return result;
+	}
+
+	protected void implTestEncodeCharBufferByteBufferbooleanException(
+			boolean endOfInput) throws CharacterCodingException {
+		ByteBuffer out = ByteBuffer.allocate(100);
+
+		// MalformedException:
+		CharBuffer in = getMalformedCharBuffer();
+		encoder.onMalformedInput(CodingErrorAction.REPORT);
+		encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+		if (in != null) {
+			encoder.reset();
+			CoderResult r = encoder.encode(in, out, endOfInput);
+			assertTrue(r.isMalformed());
+
+			encoder.reset();
+			out.clear();
+			in.rewind();
+			encoder.onMalformedInput(CodingErrorAction.IGNORE);
+			assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+					endOfInput));
+			assertCodingErrorAction(endOfInput, out, in, unibytes);
+
+			encoder.reset();
+			out.clear();
+			in.rewind();
+			encoder.onMalformedInput(CodingErrorAction.REPLACE);
+			assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+					endOfInput));
+			assertCodingErrorAction(endOfInput, out, in, unibytesWithRep);
+		} else {
+			System.out.println("Cannot find malformed char buffer for "
+					+ cs.name());
+		}
+
+		// Unmapped Exception:
+		in = getUnmapCharBuffer();
+		encoder.onMalformedInput(CodingErrorAction.REPORT);
+		encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+		if (in != null) {
+			encoder.reset();
+			out.clear();
+			assertTrue(encoder.encode(in, out, endOfInput).isUnmappable());
+
+			encoder.reset();
+			out.clear();
+			in.rewind();
+			encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+			assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+					endOfInput));
+			assertCodingErrorAction(endOfInput, out, in, unibytes);
+
+			encoder.reset();
+			out.clear();
+			in.rewind();
+			encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+			assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+					endOfInput));
+			assertCodingErrorAction(endOfInput, out, in, unibytesWithRep);
+		} else {
+			System.out.println("Cannot find unmapped char buffer for "
+					+ cs.name());
+		}
+
+		// RuntimeException
+		try {
+			encoder.encode(getExceptionCharBuffer());
+			fail("should throw runtime exception");
+		} catch (RuntimeException e) {
+		}
+	}
+
+	private void assertCodingErrorAction(boolean endOfInput, ByteBuffer out,
+			CharBuffer in, byte[] expect) {
+		if (endOfInput) {
+			assertByteArray(out, addSurrogate(expect));
+		} else {
+			in.rewind();
+			assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+					endOfInput));
+			in.rewind();
+			assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+			assertByteArray(out, addSurrogate(duplicateByteArray(expect, 3)));
+		}
+	}
+
+	/*
+	 * Class under test for CoderResult flush(ByteBuffer)
+	 */
+	public void testFlush() throws CharacterCodingException {
+		ByteBuffer out = ByteBuffer.allocate(6);
+		CharBuffer in = CharBuffer.wrap("aaa");
+		assertEquals(in.remaining(), 3);
+
+		// by encode facade, so that internal state will be wrong
+		encoder.encode(CharBuffer.wrap("testFlush"), ByteBuffer.allocate(20),
+				true);
+		assertSame(CoderResult.UNDERFLOW, encoder
+				.flush(ByteBuffer.allocate(50)));
+	}
+
+	/*
+	 * test isLegalReplacement(byte[])
+	 */
+	public void test_isLegalReplacement_null() {
+		try {
+			encoder.isLegalReplacement(null);
+			fail("should throw null pointer exception");
+		} catch (NullPointerException e) {
+		}
+	}
+
+	public void test_isLegalReplacement_good() {
+		assertTrue(encoder.isLegalReplacement(specifiedReplacement));
+	}
+
+	public void test_isLegalReplacement_bad() {
+		assertTrue(encoder.isLegalReplacement(new byte[200]));
+		byte[] ba = getIllegalByteArray();
+		if (ba != null) {
+			assertFalse(encoder.isLegalReplacement(ba));
+		}
+	}
+
+	public void test_isLegalReplacement_empty_array() {
+		// ISO, ASC, GB, UTF8 encoder will throw exception in RI
+		// others will pass
+		assertTrue(encoder.isLegalReplacement(new byte[0]));
+	}
+
+	public void testOnMalformedInput() {
+		assertSame(CodingErrorAction.REPORT, encoder.malformedInputAction());
+		try {
+			encoder.onMalformedInput(null);
+			fail("should throw null pointer exception");
+		} catch (IllegalArgumentException e) {
+		}
+		encoder.onMalformedInput(CodingErrorAction.IGNORE);
+		assertSame(CodingErrorAction.IGNORE, encoder.malformedInputAction());
+	}
+
+	public void testOnUnmappableCharacter() {
+		assertSame(CodingErrorAction.REPORT, encoder
+				.unmappableCharacterAction());
+		try {
+			encoder.onUnmappableCharacter(null);
+			fail("should throw null pointer exception");
+		} catch (IllegalArgumentException e) {
+		}
+		encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+		assertSame(CodingErrorAction.IGNORE, encoder
+				.unmappableCharacterAction());
+	}
+
+	public void testReplacement() {
+		try {
+			encoder.replaceWith(null);
+			fail("should throw null pointer exception");
+		} catch (IllegalArgumentException e) {
+		}
+		try {
+			encoder.replaceWith(new byte[0]);
+			fail("should throw null pointer exception");
+		} catch (IllegalArgumentException e) {
+		}
+		try {
+			encoder.replaceWith(new byte[100]);
+			fail("should throw null pointer exception");
+		} catch (IllegalArgumentException e) {
+		}
+
+		byte[] nr = getLegalByteArray();
+		assertSame(encoder, encoder.replaceWith(nr));
+		assertSame(nr, encoder.replacement());
+
+		nr = getIllegalByteArray();
+		try {
+			encoder.replaceWith(new byte[100]);
+			fail();
+		} catch (IllegalArgumentException e) {
+		}
+	}
+
+	protected byte[] getLegalByteArray() {
+		return new byte[] { 'a' };
+	}
+
+	protected byte[] getIllegalByteArray() {
+		return new byte[155];
+	}
+
+	/*
+	 * Mock subclass of CharsetEncoder For protected method test
+	 */
+	public static class MockCharsetEncoder extends CharsetEncoder {
+
+		boolean flushed = false;
+
+		public boolean isFlushed() {
+			boolean result = flushed;
+			flushed = false;
+			return result;
+		}
+
+		public boolean isLegalReplacement(byte[] ba) {
+			if (ba.length == 155) {// specified magic number, return false
+				return false;
+			}
+			return super.isLegalReplacement(ba);
+		}
+
+		public MockCharsetEncoder(Charset cs, float aver, float max) {
+			super(cs, aver, max);
+		}
+
+		public MockCharsetEncoder(Charset cs, float aver, float max,
+				byte[] replacement) {
+			super(cs, aver, max, replacement);
+		}
+
+		protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+			int inPosition = in.position();
+			char[] input = new char[in.remaining()];
+			in.get(input);
+			String result = new String(input);
+			if (result.startsWith("malform")) {
+				// reset the cursor to the error position
+				in.position(inPosition);
+				// in.position(0);
+				// set the error length
+				return CoderResult.malformedForLength("malform".length());
+			} else if (result.startsWith("unmap")) {
+				// reset the cursor to the error position
+				in.position(inPosition);
+				// in.position(0);
+				// set the error length
+				return CoderResult.unmappableForLength("unmap".length());
+			} else if (result.startsWith("runtime")) {
+				// reset the cursor to the error position
+				in.position(0);
+				// set the error length
+				throw new RuntimeException("runtime");
+			}
+			int inLeft = input.length;
+			int outLeft = out.remaining();
+			CoderResult r = CoderResult.UNDERFLOW;
+			int length = inLeft;
+			if (outLeft < inLeft) {
+				r = CoderResult.OVERFLOW;
+				length = outLeft;
+				in.position(inPosition + outLeft);
+			}
+			for (int i = 0; i < length; i++) {
+				out.put((byte) input[i]);
+			}
+			return r;
+		}
+
+		protected CoderResult implFlush(ByteBuffer out) {
+			CoderResult result = super.implFlush(out);
+			int length = 0;
+			if (out.remaining() >= 5) {
+				length = 5;
+				result = CoderResult.UNDERFLOW;
+				flushed = true;
+				// for (int i = 0; i < length; i++) {
+				// out.put((byte)'f');
+				// }
+			} else {
+				length = out.remaining();
+				result = CoderResult.OVERFLOW;
+			}
+			return result;
+		}
+
+		protected void implReplaceWith(byte[] ba) {
+			assertSame(ba, replacement());
+		}
+
+	}
+
+	/*
+	 * mock charset for test encoder initialization
+	 */
+	public static class MockCharset extends Charset {
+		protected MockCharset(String arg0, String[] arg1) {
+			super(arg0, arg1);
+		}
+
+		public boolean contains(Charset arg0) {
+			return false;
+		}
+
+		public CharsetDecoder newDecoder() {
+			return new CharsetDecoderTest.MockCharsetDecoder(this,
+					(float) AVER_BYTES, MAX_BYTES);
+		}
+
+		public CharsetEncoder newEncoder() {
+			return new MockCharsetEncoder(this, (float) AVER_BYTES, MAX_BYTES);
+		}
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
new file mode 100644
index 0000000..b38728a
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
@@ -0,0 +1,406 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.spi.CharsetProvider;
+import java.util.Iterator;
+import java.util.Vector;
+
+import junit.framework.TestCase;
+import tests.api.java.nio.charset.CharsetTest.MockCharset;
+
+/**
+ * Test charset providers managed by Charset.
+ */
+public class CharsetProviderTest extends TestCase {
+
+	static String CONFIG_FILE1 = null;
+
+
+	static MockCharset charset1 = new MockCharset("mockCharset00",
+			new String[] { "mockCharset01", "mockCharset02" });
+
+	static MockCharset charset2 = new MockCharset("mockCharset10",
+			new String[] { "mockCharset11", "mockCharset12" });
+
+	/**
+	 * @param arg0
+	 */
+	public CharsetProviderTest(String arg0) {
+		super(arg0);
+                CONFIG_FILE1 = System.getProperty("user.dir") + "/resources";
+
+		String sep = System.getProperty("file.separator");
+
+		if (!CONFIG_FILE1.endsWith(sep)) {
+			CONFIG_FILE1 += sep;
+		}
+		CONFIG_FILE1 += "META-INF" + sep + "services" + sep
+				+ "java.nio.charset.spi.CharsetProvider";
+	}
+
+	/*
+	 * Write the string to the config file.
+	 */
+	private void setupFile(String path, String content) throws Exception {
+		String sep = System.getProperty("file.separator");
+		int sepIndex = path.lastIndexOf(sep);
+		File f = new File(path.substring(0, sepIndex));
+		f.mkdirs();
+
+		FileOutputStream fos = new FileOutputStream(path);
+		OutputStreamWriter writer = new OutputStreamWriter(fos, "UTF-8");
+		try {
+			writer.write(content);
+		} finally {
+			writer.close();
+		}
+	}
+
+	/*
+	 * Write the string to the config file.
+	 */
+	private void cleanupFile(String path) throws Exception {
+		File f = new File(path);
+		f.delete();
+	}
+
+	/*
+	 * Test the method isSupported(String) with charset supported by some
+	 * providers (multiple).
+	 */
+	public void testIsSupported_And_ForName_NormalProvider() throws Exception {
+		try {
+			assertFalse(Charset.isSupported("mockCharset10"));
+			assertFalse(Charset.isSupported("mockCharset11"));
+			assertFalse(Charset.isSupported("mockCharset12"));
+            try {
+                Charset.forName("mockCharset10");
+                fail("Should throw UnsupportedCharsetException!");
+            } catch (UnsupportedCharsetException e) {
+                // expected
+            }
+            try {
+                Charset.forName("mockCharset11");
+                fail("Should throw UnsupportedCharsetException!");
+            } catch (UnsupportedCharsetException e) {
+                // expected
+            }
+            try {
+                Charset.forName("mockCharset12");
+                fail("Should throw UnsupportedCharsetException!");
+            } catch (UnsupportedCharsetException e) {
+                // expected
+            }
+
+			StringBuffer sb = new StringBuffer();
+			sb.append("#comment\r");
+			sb.append("\n");
+			sb.append("\r\n");
+			sb
+					.append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t\n\r");
+			sb
+					.append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			sb = new StringBuffer();
+			sb.append(" #comment\r");
+			sb.append("\n");
+			sb.append("\r\n");
+			sb
+					.append(" \ttests.api.java.nio.charset.CharsetProviderTest$MockCharsetProvider \t\n\r");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			assertTrue(Charset.isSupported("mockCharset10"));
+			// ignore case problem in mock, intended
+			assertTrue(Charset.isSupported("MockCharset11"));
+			assertTrue(Charset.isSupported("MockCharset12"));
+			assertTrue(Charset.isSupported("MOCKCharset10"));
+			// intended case problem in mock
+			assertTrue(Charset.isSupported("MOCKCharset11"));
+			assertTrue(Charset.isSupported("MOCKCharset12"));
+
+            assertTrue(Charset.forName("mockCharset10") instanceof MockCharset);
+            assertTrue(Charset.forName("mockCharset11") instanceof MockCharset);
+            assertTrue(Charset.forName("mockCharset12") instanceof MockCharset);
+
+            assertTrue(Charset.forName("mockCharset10") == charset2);
+            // intended case problem in mock
+            Charset.forName("mockCharset11");
+            assertTrue(Charset.forName("mockCharset12") == charset2);
+		} finally {
+			cleanupFile(CONFIG_FILE1);
+		}
+	}
+
+	/*
+	 * Test the method isSupported(String) when the configuration file contains
+	 * a non-existing class name.
+	 */
+	public void testIsSupported_NonExistingClass() throws Exception {
+		try {
+			StringBuffer sb = new StringBuffer();
+			sb.append("impossible\r");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			Charset.isSupported("impossible");
+			fail("Should throw Error!");
+		} catch (Error e) {
+			// expected
+		} finally {
+			cleanupFile(CONFIG_FILE1);
+		}
+	}
+
+	/*
+	 * Test the method isSupported(String) when the configuration file contains
+	 * a non-CharsetProvider class name.
+	 */
+	public void testIsSupported_NotCharsetProviderClass() throws Exception {
+		try {
+			StringBuffer sb = new StringBuffer();
+			sb.append("java.lang.String\r");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			Charset.isSupported("impossible");
+			fail("Should throw ClassCastException!");
+		} catch (ClassCastException e) {
+			// expected
+		} finally {
+			cleanupFile(CONFIG_FILE1);
+		}
+	}
+
+	/*
+	 * Test the method forName(String) when the charset provider supports a
+	 * built-in charset.
+	 */
+	public void testForName_DuplicateWithBuiltInCharset() throws Exception {
+		try {
+			StringBuffer sb = new StringBuffer();
+			sb
+					.append("tests.api.java.nio.charset.CharsetProviderTest$MockCharsetProviderACSII\r");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			assertFalse(Charset.forName("us-ascii") instanceof MockCharset);
+			assertFalse(Charset.availableCharsets().get("us-ascii") instanceof MockCharset);
+		} finally {
+			cleanupFile(CONFIG_FILE1);
+		}
+	}
+
+	/*
+	 * Test the method forName(String) when the configuration file contains a
+	 * non-existing class name.
+	 */
+	public void testForName_NonExistingClass() throws Exception {
+		try {
+			StringBuffer sb = new StringBuffer();
+			sb.append("impossible\r");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			Charset.forName("impossible");
+			fail("Should throw Error!");
+		} catch (Error e) {
+			// expected
+		} finally {
+			cleanupFile(CONFIG_FILE1);
+		}
+	}
+
+	/*
+	 * Test the method forName(String) when the configuration file contains a
+	 * non-CharsetProvider class name.
+	 */
+	public void testForName_NotCharsetProviderClass() throws Exception {
+		try {
+			StringBuffer sb = new StringBuffer();
+			sb.append("java.lang.String\r");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			Charset.forName("impossible");
+			fail("Should throw ClassCastException!");
+		} catch (ClassCastException e) {
+			// expected
+		} finally {
+			cleanupFile(CONFIG_FILE1);
+		}
+	}
+
+	/*
+	 * Test the method availableCharsets() with charset supported by some
+	 * providers (multiple).
+	 */
+	public void testAvailableCharsets_NormalProvider() throws Exception {
+		try {
+			assertFalse(Charset.availableCharsets()
+					.containsKey("mockCharset10"));
+			assertFalse(Charset.availableCharsets()
+					.containsKey("mockCharset11"));
+			assertFalse(Charset.availableCharsets()
+					.containsKey("mockCharset12"));
+
+			StringBuffer sb = new StringBuffer();
+			sb.append("#comment\r");
+			sb.append("\n");
+			sb.append("\r\n");
+			sb
+					.append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t\n\r");
+			sb
+					.append(" \ttests.api.java.nio.charset.CharsetTest$MockCharsetProvider \t");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			sb = new StringBuffer();
+			sb.append("#comment\r");
+			sb.append("\n");
+			sb.append("\r\n");
+			sb
+					.append(" \ttests.api.java.nio.charset.CharsetProviderTest$MockCharsetProvider \t\n\r");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			assertTrue(Charset.availableCharsets().containsKey("mockCharset00"));
+			assertTrue(Charset.availableCharsets().containsKey("MOCKCharset00"));
+			assertTrue(Charset.availableCharsets().get("mockCharset00") instanceof MockCharset);
+			assertTrue(Charset.availableCharsets().get("MOCKCharset00") instanceof MockCharset);
+			assertFalse(Charset.availableCharsets()
+					.containsKey("mockCharset01"));
+			assertFalse(Charset.availableCharsets()
+					.containsKey("mockCharset02"));
+
+			assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
+			assertTrue(Charset.availableCharsets().get("MOCKCharset10") == charset2);
+			assertFalse(Charset.availableCharsets()
+					.containsKey("mockCharset11"));
+			assertFalse(Charset.availableCharsets()
+					.containsKey("mockCharset12"));
+
+			assertTrue(Charset.availableCharsets().containsKey("mockCharset10"));
+			assertTrue(Charset.availableCharsets().containsKey("MOCKCharset10"));
+			assertTrue(Charset.availableCharsets().get("mockCharset10") == charset2);
+			assertFalse(Charset.availableCharsets()
+					.containsKey("mockCharset11"));
+			assertFalse(Charset.availableCharsets()
+					.containsKey("mockCharset12"));
+		} finally {
+			cleanupFile(CONFIG_FILE1);
+		}
+	}
+
+	/*
+	 * Test the method availableCharsets(String) when the configuration file
+	 * contains a non-existing class name.
+	 */
+	public void testAvailableCharsets_NonExistingClass() throws Exception {
+		try {
+			StringBuffer sb = new StringBuffer();
+			sb.append("impossible\r");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			Charset.availableCharsets();
+			fail("Should throw Error!");
+		} catch (Error e) {
+			// expected
+		} finally {
+			cleanupFile(CONFIG_FILE1);
+		}
+	}
+
+	/*
+	 * Test the method availableCharsets(String) when the configuration file
+	 * contains a non-CharsetProvider class name.
+	 */
+	public void testAvailableCharsets_NotCharsetProviderClass()
+			throws Exception {
+		try {
+			StringBuffer sb = new StringBuffer();
+			sb.append("java.lang.String\r");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			Charset.availableCharsets();
+			fail("Should throw ClassCastException!");
+		} catch (ClassCastException e) {
+			// expected
+		} finally {
+			cleanupFile(CONFIG_FILE1);
+		}
+	}
+
+	/*
+	 * Test the method availableCharsets(String) when the configuration file
+	 * contains an illegal string.
+	 */
+	public void testAvailableCharsets_IllegalString() throws Exception {
+		try {
+			StringBuffer sb = new StringBuffer();
+			sb.append("java String\r");
+			setupFile(CONFIG_FILE1, sb.toString());
+
+			Charset.availableCharsets();
+			fail("Should throw Error!");
+		} catch (Error e) {
+			// expected
+		} finally {
+			cleanupFile(CONFIG_FILE1);
+		}
+	}
+
+    /*
+     * Mock charset provider.
+     */
+    public static class MockCharsetProvider extends CharsetProvider {
+
+        public Charset charsetForName(String charsetName) {
+            if ("MockCharset10".equalsIgnoreCase(charsetName)
+                    || "MockCharset11".equalsIgnoreCase(charsetName)
+                    || "MockCharset12".equalsIgnoreCase(charsetName)) {
+                return charset2;
+            }
+            return null;
+        }
+
+        public Iterator charsets() {
+            Vector v = new Vector();
+            v.add(charset2);
+            return v.iterator();
+        }
+    }
+
+    /*
+     * Another mock charset provider providing build-in charset "ascii".
+     */
+    public static class MockCharsetProviderACSII extends CharsetProvider {
+
+        public Charset charsetForName(String charsetName) {
+            if ("US-ASCII".equalsIgnoreCase(charsetName)
+                    || "ASCII".equalsIgnoreCase(charsetName)) {
+                return new MockCharset("US-ASCII", new String[] { "ASCII" });
+            }
+            return null;
+        }
+
+        public Iterator charsets() {
+            Vector v = new Vector();
+            v.add(new MockCharset("US-ASCII", new String[] { "ASCII" }));
+            return v.iterator();
+        }
+    }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java
new file mode 100644
index 0000000..c658c48
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java
@@ -0,0 +1,839 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.spi.CharsetProvider;
+import java.security.Permission;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.SortedMap;
+import java.util.Vector;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class java.nio.Charset.
+ */
+public class CharsetTest extends TestCase {
+
+	static MockCharset charset1 = new MockCharset("mockCharset00",
+			new String[] { "mockCharset01", "mockCharset02" });
+
+	static MockCharset charset2 = new MockCharset("mockCharset10",
+			new String[] { "mockCharset11", "mockCharset12" });
+
+	/*
+	 * @see TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		super.setUp();
+	}
+
+	/*
+	 * @see TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	/*
+	 * Test the required 6 charsets are supported.
+	 */
+	public void testRequiredCharsetSupported() {
+		assertTrue(Charset.isSupported("US-ASCII"));
+		assertTrue(Charset.isSupported("ASCII"));
+		assertTrue(Charset.isSupported("ISO-8859-1"));
+		assertTrue(Charset.isSupported("ISO8859_1"));
+		assertTrue(Charset.isSupported("UTF-8"));
+		assertTrue(Charset.isSupported("UTF8"));
+		assertTrue(Charset.isSupported("UTF-16"));
+		assertTrue(Charset.isSupported("UTF-16BE"));
+		assertTrue(Charset.isSupported("UTF-16LE"));
+
+		Charset c1 = Charset.forName("US-ASCII");
+		assertEquals("US-ASCII", Charset.forName("US-ASCII").name());
+		assertEquals("US-ASCII", Charset.forName("ASCII").name());
+		assertEquals("ISO-8859-1", Charset.forName("ISO-8859-1").name());
+		assertEquals("ISO-8859-1", Charset.forName("ISO8859_1").name());
+		assertEquals("UTF-8", Charset.forName("UTF-8").name());
+		assertEquals("UTF-8", Charset.forName("UTF8").name());
+		assertEquals("UTF-16", Charset.forName("UTF-16").name());
+		assertEquals("UTF-16BE", Charset.forName("UTF-16BE").name());
+		assertEquals("UTF-16LE", Charset.forName("UTF-16LE").name());
+
+		assertNotSame(Charset.availableCharsets(), Charset.availableCharsets());
+		// assertSame(Charset.forName("US-ASCII"), Charset.availableCharsets()
+		// .get("US-ASCII"));
+		// assertSame(Charset.forName("US-ASCII"), c1);
+		assertTrue(Charset.availableCharsets().containsKey("US-ASCII"));
+		assertTrue(Charset.availableCharsets().containsKey("ISO-8859-1"));
+		assertTrue(Charset.availableCharsets().containsKey("UTF-8"));
+		assertTrue(Charset.availableCharsets().containsKey("UTF-16"));
+		assertTrue(Charset.availableCharsets().containsKey("UTF-16BE"));
+		assertTrue(Charset.availableCharsets().containsKey("UTF-16LE"));
+	}
+
+	/*
+	 * Test the method isSupported(String) with null.
+	 */
+	public void testIsSupported_Null() {
+		try {
+			Charset.isSupported(null);
+			fail("Should throw IllegalArgumentException!");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method isSupported(String) with empty string.
+	 *
+	 */
+	public void testIsSupported_EmptyString() {
+		try {
+			Charset.isSupported("");
+		} catch (IllegalArgumentException e) {
+                        // FIXME: Commented out since RI does throw IAE
+                        // fail("Should not throw IllegalArgumentException!");
+		}
+	}
+
+	/*
+	 * Test the method isSupported(String) with a string starting with ".".
+	 *
+	 */
+	public void testIsSupported_InvalidInitialCharacter() {
+		try {
+			Charset.isSupported(".char");
+		} catch (IllegalArgumentException e) {
+			fail("Should not throw IllegalArgumentException!");
+		}
+	}
+
+	/*
+	 * Test the method isSupported(String) with illegal charset name.
+	 */
+	public void testIsSupported_IllegalName() {
+		try {
+			Charset.isSupported(" ///#$$");
+			fail("Should throw IllegalCharsetNameException!");
+		} catch (IllegalCharsetNameException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method isSupported(String) with not supported charset name.
+	 */
+	public void testIsSupported_NotSupported() {
+		assertFalse(Charset.isSupported("impossible"));
+	}
+
+	/*
+	 * Test the method forName(String) with null.
+	 */
+	public void testForName_Null() {
+		try {
+			Charset.forName(null);
+			fail("Should throw IllegalArgumentException!");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method forName(String) with empty string.
+	 */
+	public void testForName_EmptyString() {
+		try {
+			Charset.forName("");
+			fail("Should throw IllegalArgumentException!");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method forName(String) with a string starting with ".".
+	 */
+	public void testForName_InvalidInitialCharacter() {
+		try {
+			Charset.forName(".char");
+			fail("Should throw IllegalArgumentException!");
+		} catch (IllegalArgumentException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method forName(String) with illegal charset name.
+	 */
+	public void testForName_IllegalName() {
+		try {
+			Charset.forName(" ///#$$");
+			fail("Should throw IllegalCharsetNameException!");
+		} catch (IllegalCharsetNameException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method forName(String) with not supported charset name.
+	 */
+	public void testForName_NotSupported() {
+		try {
+			Charset.forName("impossible");
+			fail("Should throw UnsupportedCharsetException!");
+		} catch (UnsupportedCharsetException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the constructor with normal parameter values.
+	 */
+	public void testConstructor_Normal() {
+		final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+		MockCharset c = new MockCharset(mockName, new String[] { "mock" });
+		assertEquals(mockName, c.name());
+		assertEquals(mockName, c.displayName());
+		assertEquals(mockName, c.displayName(Locale.getDefault()));
+		assertEquals("mock", c.aliases().toArray()[0]);
+		assertEquals(1, c.aliases().toArray().length);
+	}
+
+	/*
+	 * Test the constructor with empty canonical name.
+	 *
+	 */
+	public void testConstructor_EmptyCanonicalName() {
+		try {
+			new MockCharset("", new String[0]);
+		} catch (IllegalCharsetNameException e) {
+                        // FIXME: Commented out since RI does throw IAE
+                        // fail("Should not throw IllegalArgumentException!");
+		}
+	}
+
+	/*
+	 * Test the constructor with illegal canonical name: starting with neither a
+	 * digit nor a letter.
+	 *
+	 */
+	public void testConstructor_IllegalCanonicalName_Initial() {
+		try {
+			new MockCharset("-123", new String[] { "mock" });
+		} catch (IllegalCharsetNameException e) {
+			fail("Should not throw IllegalArgumentException!");
+		}
+	}
+
+	/*
+	 * Test the constructor with illegal canonical name, illegal character in
+	 * the middle.
+	 */
+	public void testConstructor_IllegalCanonicalName_Middle() {
+		try {
+			new MockCharset("1%%23", new String[] { "mock" });
+			fail("Should throw IllegalCharsetNameException!");
+		} catch (IllegalCharsetNameException e) {
+			// expected
+		}
+		try {
+			new MockCharset("1//23", new String[] { "mock" });
+			fail("Should throw IllegalCharsetNameException!");
+		} catch (IllegalCharsetNameException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the constructor with null canonical name.
+	 */
+	public void testConstructor_NullCanonicalName() {
+		try {
+			MockCharset c = new MockCharset(null, new String[] { "mock" });
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the constructor with null aliases.
+	 */
+	public void testConstructor_NullAliases() {
+		MockCharset c = new MockCharset("mockChar", null);
+		assertEquals("mockChar", c.name());
+		assertEquals("mockChar", c.displayName());
+		assertEquals("mockChar", c.displayName(Locale.getDefault()));
+		assertEquals(0, c.aliases().toArray().length);
+	}
+
+	/*
+	 * Test the constructor with a null aliases.
+	 */
+	public void testConstructor_NullAliase() {
+		try {
+			new MockCharset("mockChar", new String[] { "mock", null });
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the constructor with no aliases.
+	 */
+	public void testConstructor_NoAliases() {
+		MockCharset c = new MockCharset("mockChar", new String[0]);
+		assertEquals("mockChar", c.name());
+		assertEquals("mockChar", c.displayName());
+		assertEquals("mockChar", c.displayName(Locale.getDefault()));
+		assertEquals(0, c.aliases().toArray().length);
+	}
+
+	/*
+	 * Test the constructor with empty aliases.
+	 *
+	 */
+	public void testConstructor_EmptyAliases() {
+		try {
+			new MockCharset("mockChar", new String[] { "" });
+		} catch (IllegalCharsetNameException e) {
+                        // FIXME: Commented out since RI does throw IAE
+			// fail("Should not throw IllegalArgumentException!");
+		}
+	}
+
+	/*
+	 * Test the constructor with illegal aliases: starting with neither a digit
+	 * nor a letter.
+	 *
+	 */
+	public void testConstructor_IllegalAliases_Initial() {
+		try {
+			new MockCharset("mockChar", new String[] { "mock", "-123" });
+		} catch (IllegalCharsetNameException e) {
+			fail("Should not throw IllegalArgumentException!");
+		}
+	}
+
+	/*
+	 * Test the constructor with illegal aliase, illegal character in the
+	 * middle.
+	 */
+	public void testConstructor_IllegalAliases_Middle() {
+		try {
+			new MockCharset("mockChar", new String[] { "mock", "22##ab" });
+			fail("Should throw IllegalCharsetNameException!");
+		} catch (IllegalCharsetNameException e) {
+			// expected
+		}
+		try {
+			new MockCharset("mockChar", new String[] { "mock", "22%%ab" });
+			fail("Should throw IllegalCharsetNameException!");
+		} catch (IllegalCharsetNameException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method aliases() with multiple aliases. Most conditions have
+	 * been tested in the testcases for the constructors.
+	 */
+	public void testAliases_Multiple() {
+		final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+		MockCharset c = new MockCharset("mockChar", new String[] { "mock",
+				mockName, "mock2" });
+		assertEquals("mockChar", c.name());
+		assertEquals(3, c.aliases().size());
+		assertTrue(c.aliases().contains("mock"));
+		assertTrue(c.aliases().contains(mockName));
+		assertTrue(c.aliases().contains("mock2"));
+
+		try {
+			c.aliases().clear();
+			fail("Should throw UnsupportedOperationException!");
+		} catch (UnsupportedOperationException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method aliases() with duplicate aliases, one same with its
+	 * canonical name.
+	 */
+	public void testAliases_Duplicate() {
+		final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+		MockCharset c = new MockCharset("mockChar", new String[] { "mockChar",
+				"mock", mockName, "mock", "mockChar", "mock", "mock2" });
+		assertEquals("mockChar", c.name());
+		assertEquals(4, c.aliases().size());
+		assertTrue(c.aliases().contains("mockChar"));
+		assertTrue(c.aliases().contains("mock"));
+		assertTrue(c.aliases().contains(mockName));
+		assertTrue(c.aliases().contains("mock2"));
+	}
+
+	/*
+	 * Test the method canEncode(). Test the default return value.
+	 */
+	public void testCanEncode() {
+		MockCharset c = new MockCharset("mock", null);
+		assertTrue(c.canEncode());
+	}
+
+	/*
+	 * Test the method isRegistered(). Test the default return value.
+	 */
+	public void testIsRegistered() {
+		MockCharset c = new MockCharset("mock", null);
+		assertTrue(c.isRegistered());
+	}
+
+	/*
+	 * The name() method has been tested by the testcases for the constructor.
+	 */
+	public void testName() {
+		// already covered by testConstructor_XXX series
+	}
+
+	/*
+	 * The displayName() method have been tested by the testcases for the
+	 * constructor.
+	 */
+	public void testDisplayName() {
+		// already covered by testConstructor_XXX series
+	}
+
+	/*
+	 * Test displayName(Locale) with null.
+	 */
+	public void testDisplayName_Locale_Null() {
+		MockCharset c = new MockCharset("mock", null);
+		assertEquals("mock", c.displayName(null));
+	}
+
+	/*
+	 * Test the method compareTo(Object) with normal conditions.
+	 */
+	public void testCompareTo_Normal() {
+		MockCharset c1 = new MockCharset("mock", null);
+		assertEquals(0, c1.compareTo(c1));
+
+		MockCharset c2 = new MockCharset("Mock", null);
+		assertEquals(0, c1.compareTo(c2));
+
+		c2 = new MockCharset("mock2", null);
+		assertTrue(c1.compareTo(c2) < 0);
+		assertTrue(c2.compareTo(c1) > 0);
+
+		c2 = new MockCharset("mack", null);
+		assertTrue(c1.compareTo(c2) > 0);
+		assertTrue(c2.compareTo(c1) < 0);
+
+		c2 = new MockCharset("m.", null);
+		assertTrue(c1.compareTo(c2) > 0);
+		assertTrue(c2.compareTo(c1) < 0);
+
+		c2 = new MockCharset("m:", null);
+		assertEquals("mock".compareToIgnoreCase("m:"), c1.compareTo(c2));
+		assertEquals("m:".compareToIgnoreCase("mock"), c2.compareTo(c1));
+
+		c2 = new MockCharset("m-", null);
+		assertTrue(c1.compareTo(c2) > 0);
+		assertTrue(c2.compareTo(c1) < 0);
+
+		c2 = new MockCharset("m_", null);
+		assertTrue(c1.compareTo(c2) > 0);
+		assertTrue(c2.compareTo(c1) < 0);
+	}
+
+	/*
+	 * Test the method compareTo(Object) with null param.
+	 */
+	public void testCompareTo_Null() {
+		MockCharset c1 = new MockCharset("mock", null);
+		try {
+			c1.compareTo(null);
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method compareTo(Object) with another kind of charset object.
+	 */
+	public void testCompareTo_DiffCharsetClass() {
+		MockCharset c1 = new MockCharset("mock", null);
+		MockCharset2 c2 = new MockCharset2("Mock", new String[] { "myname" });
+		assertEquals(0, c1.compareTo(c2));
+		assertEquals(0, c2.compareTo(c1));
+	}
+
+	/*
+	 * Test the method equals(Object) with null param.
+	 */
+	public void testEquals_Normal() {
+		MockCharset c1 = new MockCharset("mock", null);
+		MockCharset2 c2 = new MockCharset2("mock", null);
+		assertTrue(c1.equals(c2));
+		assertTrue(c2.equals(c1));
+
+		c2 = new MockCharset2("Mock", null);
+		assertFalse(c1.equals(c2));
+		assertFalse(c2.equals(c1));
+	}
+
+	/*
+	 * Test the method equals(Object) with normal conditions.
+	 */
+	public void testEquals_Null() {
+		MockCharset c1 = new MockCharset("mock", null);
+		assertFalse(c1.equals(null));
+	}
+
+	/*
+	 * Test the method equals(Object) with another kind of charset object.
+	 */
+	public void testEquals_NonCharsetObject() {
+		MockCharset c1 = new MockCharset("mock", null);
+		assertFalse(c1.equals("test"));
+	}
+
+	/*
+	 * Test the method equals(Object) with another kind of charset object.
+	 */
+	public void testEquals_DiffCharsetClass() {
+		MockCharset c1 = new MockCharset("mock", null);
+		MockCharset2 c2 = new MockCharset2("mock", null);
+		assertTrue(c1.equals(c2));
+		assertTrue(c2.equals(c1));
+	}
+
+	/*
+	 * Test the method hashCode().
+	 */
+	public void testHashCode_DiffCharsetClass() {
+		MockCharset c1 = new MockCharset("mock", null);
+		assertEquals(c1.hashCode(), "mock".hashCode());
+
+		final String mockName = "mockChar1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.:-_";
+		c1 = new MockCharset(mockName, new String[] { "mockChar", "mock",
+				mockName, "mock", "mockChar", "mock", "mock2" });
+		assertEquals(mockName.hashCode(), c1.hashCode());
+	}
+
+	/*
+	 * Test the method encode(CharBuffer) under normal condition.
+	 */
+	public void testEncode_CharBuffer_Normal() throws Exception {
+		MockCharset c1 = new MockCharset("testEncode_CharBuffer_Normal_mock", null);
+		ByteBuffer bb = c1.encode(CharBuffer.wrap("abcdefg"));
+		assertEquals("abcdefg", new String(bb.array(), "iso8859-1"));
+		bb = c1.encode(CharBuffer.wrap(""));
+		assertEquals("", new String(bb.array(), "iso8859-1"));
+	}
+
+	/*
+	 * Test the method encode(CharBuffer) with an unmappable char.
+	 */
+	public void testEncode_CharBuffer_Unmappable() throws Exception {
+		Charset c1 = Charset.forName("iso8859-1");
+		ByteBuffer bb = c1.encode(CharBuffer.wrap("abcd\u5D14efg"));
+		assertEquals(new String(bb.array(), "iso8859-1"), "abcd"
+				+ new String(c1.newEncoder().replacement(), "iso8859-1")
+				+ "efg");
+	}
+
+	/*
+	 * Test the method encode(CharBuffer) with null CharBuffer.
+	 */
+	public void testEncode_CharBuffer_NullCharBuffer() {
+		MockCharset c = new MockCharset("mock", null);
+		try {
+			c.encode((CharBuffer) null);
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method encode(CharBuffer) with null encoder.
+	 */
+	public void testEncode_CharBuffer_NullEncoder() {
+		MockCharset2 c = new MockCharset2("mock2", null);
+		try {
+			c.encode(CharBuffer.wrap("hehe"));
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method encode(String) under normal condition.
+	 */
+	public void testEncode_String_Normal() throws Exception {
+		MockCharset c1 = new MockCharset("testEncode_String_Normal_mock", null);
+		ByteBuffer bb = c1.encode("abcdefg");
+		assertEquals("abcdefg", new String(bb.array(), "iso8859-1"));
+		bb = c1.encode("");
+		assertEquals("", new String(bb.array(), "iso8859-1"));
+	}
+
+	/*
+	 * Test the method encode(String) with an unmappable char.
+	 */
+	public void testEncode_String_Unmappable() throws Exception {
+		Charset c1 = Charset.forName("iso8859-1");
+		ByteBuffer bb = c1.encode("abcd\u5D14efg");
+		assertEquals(new String(bb.array(), "iso8859-1"), "abcd"
+				+ new String(c1.newEncoder().replacement(), "iso8859-1")
+				+ "efg");
+	}
+
+	/*
+	 * Test the method encode(String) with null CharBuffer.
+	 */
+	public void testEncode_String_NullString() {
+		MockCharset c = new MockCharset("mock", null);
+		try {
+			c.encode((String) null);
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method encode(String) with null encoder.
+	 */
+	public void testEncode_String_NullEncoder() {
+
+		MockCharset2 c = new MockCharset2("mock2", null);
+		try {
+			c.encode("hehe");
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method decode(ByteBuffer) under normal condition.
+	 */
+	public void testDecode_Normal() throws Exception {
+		MockCharset c1 = new MockCharset("mock", null);
+		CharBuffer cb = c1.decode(ByteBuffer.wrap("abcdefg"
+				.getBytes("iso8859-1")));
+		assertEquals("abcdefg", new String(cb.array()));
+		cb = c1.decode(ByteBuffer.wrap("".getBytes("iso8859-1")));
+		assertEquals("", new String(cb.array()));
+	}
+
+	/*
+	 * Test the method decode(ByteBuffer) with a malformed input.
+	 */
+	public void testDecode_Malformed() throws Exception {
+		Charset c1 = Charset.forName("iso8859-1");
+		CharBuffer cb = c1.decode(ByteBuffer.wrap("abcd\u5D14efg"
+				.getBytes("iso8859-1")));
+		byte[] replacement = c1.newEncoder().replacement();
+		assertEquals(new String(cb.array()).trim(), "abcd" + new String(replacement, "iso8859-1")
+				+ "efg");
+	}
+
+	/*
+	 * Test the method decode(ByteBuffer) with null CharBuffer.
+	 */
+	public void testDecode_NullByteBuffer() {
+		MockCharset c = new MockCharset("mock", null);
+		try {
+			c.decode(null);
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method decode(ByteBuffer) with null encoder.
+	 */
+	public void testDecode_NullDecoder() {
+		MockCharset2 c = new MockCharset2("mock2", null);
+		try {
+			c.decode(ByteBuffer.wrap("hehe".getBytes()));
+			fail("Should throw NullPointerException!");
+		} catch (NullPointerException e) {
+			// expected
+		}
+	}
+
+	/*
+	 * Test the method toString().
+	 */
+	public void testToString() {
+		MockCharset c1 = new MockCharset("mock", null);
+		assertTrue(-1 != c1.toString().indexOf("mock"));
+	}
+
+    /**
+     * @tests java.nio.charset.Charset#availableCharsets()
+     */
+    public void test_availableCharsets() throws Exception {
+        // regression test for Harmony-1051
+        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(null);
+            SortedMap<String, Charset> charsets = Charset.availableCharsets();
+            // make sure "mockCharset00" is loaded by MockCharsetProvider
+            assertTrue(charsets.containsKey("mockCharset00"));
+        } finally {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+    }
+
+    /**
+     * @tests java.nio.charset.Charset#availableCharsets()
+     */
+    public void test_forNameLString() throws Exception {
+        // regression test for Harmony-1051
+        ClassLoader originalClassLoader = Thread.currentThread()
+                .getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(null);
+            // make sure "mockCharset00" is loaded by MockCharsetProvider
+            assertNotNull(Charset.forName("mockCharset00"));
+        } finally {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+    }
+
+	/*
+	 * Mock charset class.
+	 */
+	static final class MockCharset extends Charset {
+
+		public MockCharset(String canonicalName, String[] aliases) {
+			super(canonicalName, aliases);
+		}
+
+		public boolean contains(Charset cs) {
+			return false;
+		}
+
+		public CharsetDecoder newDecoder() {
+			return new MockDecoder(this);
+		}
+
+		public CharsetEncoder newEncoder() {
+			return new MockEncoder(this);
+		}
+	}
+
+	/*
+	 * Another mock charset class.
+	 */
+	static class MockCharset2 extends Charset {
+
+		public MockCharset2(String canonicalName, String[] aliases) {
+			super(canonicalName, aliases);
+		}
+
+		public boolean contains(Charset cs) {
+			return false;
+		}
+
+		public CharsetDecoder newDecoder() {
+			return null;
+		}
+
+		public CharsetEncoder newEncoder() {
+			return null;
+		}
+	}
+
+	/*
+	 * Mock encoder.
+	 */
+	static class MockEncoder extends java.nio.charset.CharsetEncoder {
+
+		public MockEncoder(Charset cs) {
+			super(cs, 1, 3, new byte[] { (byte) '?' });
+		}
+
+		protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+			while (in.remaining() > 0) {
+				out.put((byte) in.get());
+				// out.put((byte) '!');
+			}
+			return CoderResult.UNDERFLOW;
+		}
+	}
+
+	/*
+	 * Mock decoder.
+	 */
+	static class MockDecoder extends java.nio.charset.CharsetDecoder {
+
+		public MockDecoder(Charset cs) {
+			super(cs, 1, 10);
+		}
+
+		protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+			while (in.remaining() > 0) {
+				out.put((char) in.get());
+			}
+			return CoderResult.UNDERFLOW;
+		}
+	}
+
+	/*
+	 * Mock charset provider.
+	 */
+	public static class MockCharsetProvider extends CharsetProvider {
+
+		public Charset charsetForName(String charsetName) {
+			if ("MockCharset00".equalsIgnoreCase(charsetName)
+					|| "MockCharset01".equalsIgnoreCase(charsetName)
+					|| "MockCharset02".equalsIgnoreCase(charsetName)) {
+				return new MockCharset("mockCharset00", new String[] {
+						"mockCharset01", "mockCharset02" });
+			}
+			return null;
+		}
+
+		public Iterator charsets() {
+			Vector v = new Vector();
+			v.add(new MockCharset("mockCharset00", new String[] {
+					"mockCharset01", "mockCharset02" }));
+			return v.iterator();
+		}
+	}
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CoderResultTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CoderResultTest.java
new file mode 100644
index 0000000..469fc98
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CoderResultTest.java
@@ -0,0 +1,265 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.charset.CoderResult;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class java.nio.charset.CoderResult.
+ */
+public class CoderResultTest extends TestCase {
+
+	/*
+	 * @see TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		super.setUp();
+	}
+
+	/*
+	 * @see TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	/*
+	 * Test the constant OVERFLOW and UNDERFLOW.
+	 */
+	public void testConstants() throws Exception {
+		assertNotSame(CoderResult.OVERFLOW, CoderResult.UNDERFLOW);
+
+		assertNotNull(CoderResult.OVERFLOW);
+		assertFalse(CoderResult.OVERFLOW.isError());
+		assertFalse(CoderResult.OVERFLOW.isMalformed());
+		assertFalse(CoderResult.OVERFLOW.isUnderflow());
+		assertFalse(CoderResult.OVERFLOW.isUnmappable());
+		assertTrue(CoderResult.OVERFLOW.isOverflow());
+		assertTrue(CoderResult.OVERFLOW.toString().indexOf("OVERFLOW") != -1);
+		try {
+			CoderResult.OVERFLOW.throwException();
+			fail("Should throw BufferOverflowException");
+		} catch (BufferOverflowException ex) {
+			// expected
+		}
+		try {
+			CoderResult.OVERFLOW.length();
+			fail("Should throw UnsupportedOperationException");
+		} catch (UnsupportedOperationException ex) {
+			// expected
+		}
+
+		assertNotNull(CoderResult.UNDERFLOW);
+		assertFalse(CoderResult.UNDERFLOW.isError());
+		assertFalse(CoderResult.UNDERFLOW.isMalformed());
+		assertTrue(CoderResult.UNDERFLOW.isUnderflow());
+		assertFalse(CoderResult.UNDERFLOW.isUnmappable());
+		assertFalse(CoderResult.UNDERFLOW.isOverflow());
+		assertTrue(CoderResult.UNDERFLOW.toString().indexOf("UNDERFLOW") != -1);
+		try {
+			CoderResult.UNDERFLOW.throwException();
+			fail("Should throw BufferOverflowException");
+		} catch (BufferUnderflowException ex) {
+			// expected
+		}
+		try {
+			CoderResult.UNDERFLOW.length();
+			fail("Should throw UnsupportedOperationException");
+		} catch (UnsupportedOperationException ex) {
+			// expected
+		}
+	}
+
+	/**
+	 * Test method isError().
+	 * 
+	 */
+	public void testIsError() {
+		assertFalse(CoderResult.UNDERFLOW.isError());
+		assertFalse(CoderResult.OVERFLOW.isError());
+		assertTrue(CoderResult.malformedForLength(1).isError());
+		assertTrue(CoderResult.unmappableForLength(1).isError());
+	}
+
+	/**
+	 * Test method isMalformed().
+	 * 
+	 */
+	public void testIsMalformed() {
+		assertFalse(CoderResult.UNDERFLOW.isMalformed());
+		assertFalse(CoderResult.OVERFLOW.isMalformed());
+		assertTrue(CoderResult.malformedForLength(1).isMalformed());
+		assertFalse(CoderResult.unmappableForLength(1).isMalformed());
+	}
+
+	/**
+	 * Test method isMalformed().
+	 * 
+	 */
+	public void testIsUnmappable() {
+		assertFalse(CoderResult.UNDERFLOW.isUnmappable());
+		assertFalse(CoderResult.OVERFLOW.isUnmappable());
+		assertFalse(CoderResult.malformedForLength(1).isUnmappable());
+		assertTrue(CoderResult.unmappableForLength(1).isUnmappable());
+	}
+
+	/**
+	 * Test method isOverflow().
+	 * 
+	 */
+	public void testIsOverflow() {
+		assertFalse(CoderResult.UNDERFLOW.isOverflow());
+		assertTrue(CoderResult.OVERFLOW.isOverflow());
+		assertFalse(CoderResult.malformedForLength(1).isOverflow());
+		assertFalse(CoderResult.unmappableForLength(1).isOverflow());
+	}
+
+	/**
+	 * Test method isUnderflow().
+	 * 
+	 */
+	public void testIsUnderflow() {
+		assertTrue(CoderResult.UNDERFLOW.isUnderflow());
+		assertFalse(CoderResult.OVERFLOW.isUnderflow());
+		assertFalse(CoderResult.malformedForLength(1).isUnderflow());
+		assertFalse(CoderResult.unmappableForLength(1).isUnderflow());
+	}
+
+	/**
+	 * Test method length().
+	 * 
+	 */
+	public void testLength() {
+		try {
+			CoderResult.UNDERFLOW.length();
+			fail("Should throw UnsupportedOperationException");
+		} catch (UnsupportedOperationException ex) {
+			// expected
+		}
+		try {
+			CoderResult.OVERFLOW.length();
+			fail("Should throw UnsupportedOperationException");
+		} catch (UnsupportedOperationException ex) {
+			// expected
+		}
+
+		assertEquals(CoderResult.malformedForLength(1).length(), 1);
+		assertEquals(CoderResult.unmappableForLength(1).length(), 1);
+	}
+
+	/**
+	 * Test method malformedForLength(int).
+	 * 
+	 */
+	public void testMalformedForLength() {
+		assertNotNull(CoderResult.malformedForLength(Integer.MAX_VALUE));
+		assertNotNull(CoderResult.malformedForLength(1));
+		assertSame(CoderResult.malformedForLength(1), CoderResult
+				.malformedForLength(1));
+		assertNotSame(CoderResult.malformedForLength(1), CoderResult
+				.unmappableForLength(1));
+		assertNotSame(CoderResult.malformedForLength(2), CoderResult
+				.malformedForLength(1));
+		try {
+			CoderResult.malformedForLength(-1);
+			fail("Should throw IllegalArgumentException");
+		} catch (IllegalArgumentException ex) {
+			// expected
+		}
+		try {
+			CoderResult.malformedForLength(0);
+			fail("Should throw IllegalArgumentException");
+		} catch (IllegalArgumentException ex) {
+			// expected
+		}
+	}
+
+	/**
+	 * Test method unmappableForLength(int).
+	 * 
+	 */
+	public void testUnmappableForLength() {
+		assertNotNull(CoderResult.unmappableForLength(Integer.MAX_VALUE));
+		assertNotNull(CoderResult.unmappableForLength(1));
+		assertSame(CoderResult.unmappableForLength(1), CoderResult
+				.unmappableForLength(1));
+		assertNotSame(CoderResult.unmappableForLength(2), CoderResult
+				.unmappableForLength(1));
+		try {
+			CoderResult.unmappableForLength(-1);
+			fail("Should throw IllegalArgumentException");
+		} catch (IllegalArgumentException ex) {
+			// expected
+		}
+		try {
+			CoderResult.unmappableForLength(0);
+			fail("Should throw IllegalArgumentException");
+		} catch (IllegalArgumentException ex) {
+			// expected
+		}
+	}
+
+	/**
+	 * Test method throwException().
+	 * 
+	 */
+	public void testThrowException() throws Exception {
+		try {
+			CoderResult.OVERFLOW.throwException();
+			fail("Should throw BufferOverflowException");
+		} catch (BufferOverflowException ex) {
+			// expected
+		}
+		try {
+			CoderResult.UNDERFLOW.throwException();
+			fail("Should throw BufferOverflowException");
+		} catch (BufferUnderflowException ex) {
+			// expected
+		}
+		try {
+			CoderResult.malformedForLength(1).throwException();
+			fail("Should throw MalformedInputException");
+		} catch (MalformedInputException ex) {
+			assertEquals(ex.getInputLength(), 1);
+		}
+		try {
+			CoderResult.unmappableForLength(1).throwException();
+			fail("Should throw UnmappableCharacterException");
+		} catch (UnmappableCharacterException ex) {
+			assertEquals(ex.getInputLength(), 1);
+		}
+	}
+
+	/**
+	 * Test method toString().
+	 * 
+	 */
+	public void testToString() throws Exception {
+		assertTrue(CoderResult.OVERFLOW.toString().indexOf("OVERFLOW") != -1);
+		assertTrue(CoderResult.UNDERFLOW.toString().indexOf("UNDERFLOW") != -1);
+		assertTrue(CoderResult.malformedForLength(666).toString()
+				.indexOf("666") != -1);
+		assertTrue(CoderResult.unmappableForLength(666).toString().indexOf(
+				"666") != -1);
+	}
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CodingErrorActionTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CodingErrorActionTest.java
new file mode 100644
index 0000000..da293bb
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CodingErrorActionTest.java
@@ -0,0 +1,62 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.nio.charset.CodingErrorAction;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class java.nio.charset.CodingErrorAction
+ */
+public class CodingErrorActionTest extends TestCase {
+
+	/*
+	 * @see TestCase#setUp()
+	 */
+	protected void setUp() throws Exception {
+		super.setUp();
+	}
+
+	/*
+	 * @see TestCase#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	/*
+	 * Test the constants.
+	 */
+	public void testIGNORE() {
+		assertNotNull(CodingErrorAction.IGNORE);
+		assertNotNull(CodingErrorAction.REPLACE);
+		assertNotNull(CodingErrorAction.REPORT);
+		assertNotSame(CodingErrorAction.IGNORE, CodingErrorAction.REPLACE);
+		assertNotSame(CodingErrorAction.IGNORE, CodingErrorAction.REPORT);
+		assertNotSame(CodingErrorAction.REPLACE, CodingErrorAction.REPORT);
+	}
+
+	/*
+	 * Test the method toString().
+	 */
+	public void testToString() {
+		assertTrue(CodingErrorAction.IGNORE.toString().indexOf("IGNORE") != -1);
+		assertTrue(CodingErrorAction.REPLACE.toString().indexOf("REPLACE") != -1);
+		assertTrue(CodingErrorAction.REPORT.toString().indexOf("REPORT") != -1);
+	}
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetDecoderTest.java
new file mode 100644
index 0000000..e129c54
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetDecoderTest.java
@@ -0,0 +1,64 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * test gb18030 decoder
+ */
+public class GBCharsetDecoderTest extends CharsetDecoderTest {
+
+	protected void setUp() throws Exception {
+		cs = Charset.forName("gb18030");
+		super.setUp();
+	}
+
+	/*
+	 * @see CharsetDecoderTest#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	// // FIXME: give up this tests
+	// public void testDefaultCharsPerByte(){
+	// //assertEquals(1, decoder.averageCharsPerByte());
+	// //assertEquals(1, decoder.maxCharsPerByte());
+	// assertEquals(decoder.averageCharsPerByte(), 0.25, 0.001);
+	// assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+	// }
+
+	ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+		return null;
+	}
+
+	ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+		ByteBuffer buffer = ByteBuffer.allocate(20);
+		buffer.put(new byte[] { (byte) 0xd8 });
+		buffer.put(getByteBuffer());
+		buffer.flip();
+		return buffer;
+	}
+
+	ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+		return null;
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetEncoderTest.java
new file mode 100644
index 0000000..ab4eeea
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetEncoderTest.java
@@ -0,0 +1,89 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * test case specific activity of gb18030 charset encoder
+ */
+public class GBCharsetEncoderTest extends CharsetEncoderTest {
+
+	// charset for gb180303
+	private static final Charset CS = Charset.forName("gb18030");
+
+	/*
+	 * @see CharsetEncoderTest#setUp()
+	 */
+	protected void setUp() throws Exception {
+	  cs = CS;
+	  specifiedReplacement = new byte[] { 0x1a };
+	  super.setUp();
+	}
+
+	/*
+	 * @see CharsetEncoderTest#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	public void testCanEncodechar() {
+		// normal case for utfCS
+		assertTrue(encoder.canEncode('\u0077'));
+		assertTrue(encoder.canEncode('\uc2a3'));
+
+		// for non-mapped char
+		assertTrue(encoder.canEncode('\uc2c0'));
+	}
+
+	/*
+	 * Class under test for boolean canEncode(CharSequence)
+	 */
+	public void testCanEncodeCharSequence() {
+		// surrogate char
+
+		// valid surrogate pair
+		assertTrue(encoder.canEncode("\ud800\udc00"));
+		// invalid surrogate pair
+		assertFalse(encoder.canEncode("\ud800\udb00"));
+	}
+
+	public void testSpecificDefaultValue() {
+		assertEquals(4.0, encoder.maxBytesPerChar(), 0.0);
+		assertEquals(2.5, encoder.averageBytesPerChar(), 0.0);
+	}
+
+	CharBuffer getMalformedCharBuffer() {
+		return CharBuffer.wrap("\ud800 buffer");
+	}
+
+	CharBuffer getUnmapCharBuffer() {
+		return null;
+	}
+
+	CharBuffer getExceptionCharBuffer() {
+		return null;
+	}
+
+	protected byte[] getIllegalByteArray() {
+		return new byte[] { (byte) 0xd8, (byte) 0x00 };
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetDecoderTest.java
new file mode 100644
index 0000000..82ba9b3
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetDecoderTest.java
@@ -0,0 +1,61 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * test ISO-8859-1 decoder
+ */
+public class ISOCharsetDecoderTest extends CharsetDecoderTest {
+
+	protected void setUp() throws Exception {
+		cs = Charset.forName("iso-8859-1");
+		super.setUp();
+	}
+
+	/*
+	 * @see CharsetDecoderTest#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	// FIXME: give up this tests
+	// public void testDefaultCharsPerByte(){
+	// assertEquals(1, decoder.averageCharsPerByte());
+	// assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+	// }
+
+	ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+		// TODO how on map?
+		return null;
+
+	}
+
+	ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+		// TODO how malform
+		return null;
+	}
+
+	ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+		return null;
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetEncoderTest.java
new file mode 100644
index 0000000..8a84938
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetEncoderTest.java
@@ -0,0 +1,93 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+/**
+ * test case specific activity of iso-8859-1 charset encoder
+ */
+public class ISOCharsetEncoderTest extends CharsetEncoderTest {
+
+	// charset for iso-8859-1
+	private static final Charset CS = Charset.forName("iso-8859-1");
+
+	/*
+	 * @see CharsetEncoderTest#setUp()
+	 */
+	protected void setUp() throws Exception {
+		cs = CS;
+		super.setUp();
+	}
+
+	/*
+	 * @see CharsetEncoderTest#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	@Override public void testCanEncodeCharSequence() {
+		// normal case for isoCS
+		assertTrue(encoder.canEncode("\u0077"));
+		assertFalse(encoder.canEncode("\uc2a3"));
+		assertFalse(encoder.canEncode("\ud800\udc00"));
+	}
+
+	@Override public void testCanEncodechar() throws CharacterCodingException {
+		assertTrue(encoder.canEncode('\u0077'));
+		assertFalse(encoder.canEncode('\uc2a3'));
+	}
+
+	@Override public void testSpecificDefaultValue() {
+		assertEquals(1, encoder.averageBytesPerChar(), 0.001);
+		assertEquals(1, encoder.maxBytesPerChar(), 0.001);
+	}
+
+	CharBuffer getMalformedCharBuffer() {
+		return CharBuffer.wrap("\ud800 buffer");
+	}
+
+	CharBuffer getUnmapCharBuffer() {
+		return CharBuffer.wrap("\ud800\udc00 buffer");
+	}
+
+	CharBuffer getExceptionCharBuffer() {
+		return null;
+	}
+
+	protected byte[] getIllegalByteArray() {
+		return null;
+	}
+
+	public void testMultiStepEncode() throws CharacterCodingException {
+		encoder.onMalformedInput(CodingErrorAction.REPORT);
+		encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+		try {
+			encoder.encode(CharBuffer.wrap("\ud800\udc00"));
+			fail("should unmappable");
+		} catch (UnmappableCharacterException e) {
+		}
+		encoder.reset();
+	}
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetTest.java
new file mode 100644
index 0000000..689dbf3
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetTest.java
@@ -0,0 +1,58 @@
+/* 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 tests.api.java.nio.charset;
+
+/**
+ * Test ISO-8859-1.
+ */
+public class ISOCharsetTest extends AbstractCharsetTestCase {
+
+	/**
+	 * Constructor.
+	 */
+	public ISOCharsetTest(String arg0) {
+		super(arg0, "ISO-8859-1", new String[] { "iso-ir-100", "8859_1",
+				"ISO_8859-1", "ISO8859_1", "819", "csISOLatin1", "IBM-819",
+				"ISO_8859-1:1987", "latin1", "cp819", "ISO8859-1", "IBM819",
+				"ISO_8859_1", "l1" }, true, true);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+	 */
+	public void testEncode_Normal() {
+		String input = "ab\u5D14\u654F";
+		byte[] output = new byte[] { 97, 98,
+				this.testingCharset.newEncoder().replacement()[0],
+				this.testingCharset.newEncoder().replacement()[0] };
+		internalTestEncode(input, output);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+	 */
+	public void testDecode_Normal() {
+		byte[] input = new byte[] { 97, 98, 63, 63 };
+		char[] output = "ab??".toCharArray();
+		internalTestDecode(input, output);
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetDecoderTest.java
new file mode 100644
index 0000000..a8e1343
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetDecoderTest.java
@@ -0,0 +1,72 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * 
+ */
+public class UTF16BECharsetDecoderTest extends CharsetDecoderTest {
+
+    protected void setUp() throws Exception {
+        cs = Charset.forName("utf-16be");
+        super.setUp();
+    }
+
+    /*
+     * @see CharsetDecoderTest#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    // FIXME: give up this tests
+    // public void testDefaultCharsPerByte() {
+    // // assertEquals(1, decoder.averageCharsPerByte());
+    // // assertEquals(1, decoder.maxCharsPerByte());
+    // assertEquals(decoder.averageCharsPerByte(), 0.5, 0.001);
+    // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+    // }
+
+    ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+        // no unmap byte buffer
+        return null;
+    }
+
+    ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+        // FIXME: different here, RI can parse 0xd8d8
+        // ByteBuffer buffer = ByteBuffer.allocate(100);
+        // buffer.put((byte)0xd8);
+        // buffer.put((byte)0xd8);
+        // buffer.put(unibytes);
+        // buffer.flip();
+        // return buffer;
+        return null;
+    }
+
+    ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+        return null;
+    }
+
+    protected ByteBuffer getByteBuffer() {
+        return ByteBuffer.wrap(new byte[] { 0, 32, 0, 98, 0, 117, 0, 102, 0,
+                102, 0, 101, 0, 114 });
+    }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetEncoderTest.java
new file mode 100644
index 0000000..68bd2f5
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetEncoderTest.java
@@ -0,0 +1,108 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * TODO type def
+ */
+public class UTF16BECharsetEncoderTest extends CharsetEncoderTest {
+
+	// charset for utf-16be
+	private static final Charset CS = Charset.forName("utf-16be");
+
+	/*
+	 * @see CharsetEncoderTest#setUp()
+	 */
+	protected void setUp() throws Exception {
+		cs = CS;
+		specifiedReplacement = new byte[] { -1, -3 };
+		unibytes = new byte[] { 0, 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101,
+				0, 114 };
+
+		// unibytesWithRep = new byte[] {(byte)0xff, (byte)0xfd,0, 32, 0, 98, 0,
+		// 117, 0, 102, 0, 102, 0, 101, 0, 114};
+
+		super.setUp();
+	}
+
+	/*
+	 * @see CharsetEncoderTest#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	public void testCharsetEncoderCharsetfloatfloat() {
+		// this constructor is invalid for UTF16LE CharsetEncoder
+	}
+
+	public void testCanEncodechar() throws CharacterCodingException {
+		// normal case for utfCS
+		assertTrue(encoder.canEncode('\u0077'));
+		assertTrue(encoder.canEncode('\uc2a3'));
+
+		// for non-mapped char
+		assertTrue(encoder.canEncode('\uc2c0'));
+
+	}
+
+	public void testCanEncodeCharSequence() {
+		// normal case for utfCS
+		assertTrue(encoder.canEncode("\u0077"));
+		assertTrue(encoder.canEncode("\uc2a3"));
+
+		// for non-mapped char
+		assertTrue(encoder.canEncode("\uc2c0"));
+
+		// surrogate char for unicode
+		// 1st byte: d800-dbff
+		// 2nd byte: dc00-dfff
+		// valid surrogate pair
+		assertTrue(encoder.canEncode("\ud800\udc00"));
+		// invalid surrogate pair
+		assertFalse(encoder.canEncode("\ud800\udb00"));
+	}
+
+	public void testSpecificDefaultValue() {
+		assertEquals(2, encoder.averageBytesPerChar(), 0.001);
+		assertEquals(2, encoder.maxBytesPerChar(), 0.001);
+	}
+
+	CharBuffer getMalformedCharBuffer() {
+		return CharBuffer.wrap("\ud800 buffer");
+	}
+
+	CharBuffer getUnmapCharBuffer() {
+		return null;
+	}
+
+	CharBuffer getExceptionCharBuffer() {
+		return null;
+	}
+
+	protected byte[] getIllegalByteArray() {
+	  return new byte[] { (byte)0xd8, (byte)0x00, (byte)0xdb, (byte)0x00 };
+	}
+
+	protected byte[] getLegalByteArray() {
+		return new byte[] { (byte) 0x00, (byte) 0xd8 };
+	}
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetTest.java
new file mode 100644
index 0000000..52cee90
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetTest.java
@@ -0,0 +1,53 @@
+/* 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 tests.api.java.nio.charset;
+
+/**
+ * Test UTF-16BE.
+ */
+public class UTF16BECharsetTest extends AbstractCharsetTestCase {
+
+	/**
+	 * Constructor.
+	 */
+	public UTF16BECharsetTest(String arg0) {
+		super(arg0, "UTF-16BE", new String[] { "X-UTF-16BE", "UTF_16BE" },
+				true, true); // "ISO-10646-UCS-2"
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+	 */
+	public void testEncode_Normal() {
+		String input = "ab\u5D14\u654F";
+		byte[] output = new byte[] { 0, 97, 0, 98, 93, 20, 101, 79 };
+		internalTestEncode(input, output);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+	 */
+	public void testDecode_Normal() {
+		byte[] input = new byte[] { 0, 97, 0, 98, 93, 20, 101, 79 };
+		char[] output = "ab\u5D14\u654F".toCharArray();
+		internalTestDecode(input, output);
+	}
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetDecoderTest.java
new file mode 100644
index 0000000..c5bb408
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetDecoderTest.java
@@ -0,0 +1,118 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ *
+ */
+public class UTF16CharsetDecoderTest extends CharsetDecoderTest {
+
+    boolean bigEndian = true;
+
+    protected void setUp() throws Exception {
+        cs = Charset.forName("utf-16");
+        bom = "\ufeff";
+        super.setUp();
+    }
+
+    /*
+     * @see CharsetDecoderTest#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    protected ByteBuffer getByteBuffer() {
+        // FIXME: different here
+        // if don't specified BOM
+        // ICU default is LE
+        // JDK default is BE
+
+        // maybe start with 0xFEFF, which means big endian
+        // 0xFFFE, which means little endian
+        byte[] b = (bigEndian) ? new byte[] { -1, -2, 32, 0, 98, 0, 117, 0,
+                102, 0, 102, 0, 101, 0, 114, 0 } : new byte[] { -2, -1, 0, 32,
+                0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0, 114 };
+        return ByteBuffer.wrap(b);
+    }
+
+    protected ByteBuffer getHeadlessByteBuffer() {
+        ByteBuffer b = getByteBuffer();
+        b.position(2);
+        byte[] bytes = new byte[b.remaining()];
+        b.get(bytes);
+        return ByteBuffer.wrap(bytes);
+    }
+
+    public void testLittleEndianByteBufferCharBuffer()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        bigEndian = false;
+        implTestDecodeByteBufferCharBuffer(getByteBuffer());
+        bigEndian = true;
+    }
+
+    public void testLittleEndianReadOnlyByteBufferCharBuffer()
+            throws CharacterCodingException, UnsupportedEncodingException {
+        bigEndian = false;
+        implTestDecodeByteBufferCharBuffer(getByteBuffer().asReadOnlyBuffer());
+        bigEndian = true;
+    }
+
+    public void testLittleEndian() throws CharacterCodingException,
+            UnsupportedEncodingException {
+        bigEndian = false;
+        implTestDecodeByteBuffer();
+        bigEndian = true;
+    }
+
+    // FIXME: give up this tests
+    // public void testDefaultCharsPerByte() {
+    // // assertEquals(1, decoder.averageCharsPerByte());
+    // // assertEquals(1, decoder.maxCharsPerByte());
+    // assertEquals(decoder.averageCharsPerByte(), 0.5, 0.001);
+    // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+    // }
+
+    ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+        return null;
+    }
+
+    ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+        return null;
+        // FIXME: different here, RI can parse 0xd8d8
+        // ByteBuffer buffer = ByteBuffer.allocate(100);
+        // buffer.put((byte) -1);
+        // buffer.put((byte) -2);
+        // buffer.put((byte) 0xdc);
+        // buffer.put((byte) 0xdc);
+        // buffer.put(unibytes);
+        // buffer.flip();
+        // return buffer;
+    }
+
+    ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+        return null;
+    }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetEncoderTest.java
new file mode 100644
index 0000000..6a42d41
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetEncoderTest.java
@@ -0,0 +1,128 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+
+/**
+ * TODO type def
+ */
+public class UTF16CharsetEncoderTest extends CharsetEncoderTest {
+
+	// charset for utf-16
+	// charset for utf-16be
+	private static final Charset CS = Charset.forName("utf-16");
+
+	private static final CharsetDecoder decoder = CS.newDecoder();
+
+	/*
+	 * @see CharsetEncoderTest#setUp()
+	 */
+	protected void setUp() throws Exception {
+		cs = CS;
+		specifiedReplacement = new byte[] { -3, -1 };
+		surrogate = new byte[] { -1, -2 };
+		unibytes = new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0,
+				114, 0 };
+		unibytesWithRep = new byte[] { -3, -1, 32, 0, 98, 0, 117, 0, 102, 0,
+				102, 0, 101, 0, 114, 0 };
+		super.setUp();
+	}
+
+	/*
+	 * @see CharsetEncoderTest#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	public void testCharsetEncoderCharsetfloatfloat() {
+		// this constructor is invalid for UTF16LE CharsetEncoder
+	}
+
+	public void testCanEncodechar() throws CharacterCodingException {
+		// normal case for utfCS
+		assertTrue(encoder.canEncode('\u0077'));
+		assertTrue(encoder.canEncode('\uc2a3'));
+
+		// for non-mapped char
+		assertTrue(encoder.canEncode('\uc2c0'));
+	}
+
+	public void testCanEncodeCharSequence() {
+		// normal case for utfCS
+		assertTrue(encoder.canEncode("\u0077"));
+		assertTrue(encoder.canEncode("\uc2a3"));
+
+		// for non-mapped char
+		assertTrue(encoder.canEncode("\uc2c0"));
+
+		// surrogate char for unicode
+		// 1st byte: d800-dbff
+		// 2nd byte: dc00-dfff
+		// valid surrogate pair
+		assertTrue(encoder.canEncode("\ud800\udc00"));
+		// invalid surrogate pair
+		assertFalse(encoder.canEncode("\ud800\udb00"));
+	}
+
+	public void testSpecificDefaultValue() {
+		assertEquals(encoder.averageBytesPerChar(), 2, 0.001);
+		// assertEquals(4, encoder.maxBytesPerChar());
+		// FIXME: different here!
+		assertEquals(encoder.maxBytesPerChar(), 2, 0.001);
+	}
+
+	CharBuffer getMalformedCharBuffer() {
+		return CharBuffer.wrap("\ud800 buffer");
+	}
+
+	CharBuffer getUnmapCharBuffer() {
+		return null;
+	}
+
+	CharBuffer getExceptionCharBuffer() {
+		return null;
+	}
+
+	protected byte[] getIllegalByteArray() {
+	  return new byte[] { (byte)0xd8, (byte)0x00, (byte)0xdb, (byte)0x00 };
+	}
+
+	protected byte[] getLegalByteArray() {
+		// FIXME: Different Here!
+		// return new byte[]{(byte)0xd8, 0x00};
+		return new byte[] { (byte) 0x00, (byte) 0xd8 };
+	}
+
+	void assertByteArray(ByteBuffer out, byte[] expected) {
+		out = out.duplicate();
+		if (out.position() > 0) {
+			out.flip();
+		}
+		try {
+			assertEquals(decoder.decode(out), decoder.decode(ByteBuffer
+					.wrap(expected)));
+		} catch (CharacterCodingException e) {
+			fail(e.toString());
+		}
+	}
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetTest.java
new file mode 100644
index 0000000..61dcf49
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetTest.java
@@ -0,0 +1,51 @@
+/* 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 tests.api.java.nio.charset;
+
+/**
+ * Test UTF-16.
+ */
+public class UTF16CharsetTest extends AbstractCharsetTestCase {
+
+	/**
+	 * Constructor.
+	 */
+	public UTF16CharsetTest(String arg0) {
+		super(arg0, "UTF-16", new String[] { "UTF_16" }, true, true);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+	 */
+	public void testEncode_Normal() {
+		// TODO Auto-generated method stub
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+	 */
+	public void testDecode_Normal() {
+		// TODO Auto-generated method stub
+
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetDecoderTest.java
new file mode 100644
index 0000000..e9a8e56
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetDecoderTest.java
@@ -0,0 +1,72 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * TODO typedef
+ */
+public class UTF16LECharsetDecoderTest extends CharsetDecoderTest {
+
+    protected void setUp() throws Exception {
+        cs = Charset.forName("utf-16le");
+        super.setUp();
+    }
+
+    /*
+     * @see CharsetDecoderTest#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    // // FIXME: give up this tests
+    // public void testDefaultCharsPerByte(){
+    // // assertEquals(1, decoder.averageCharsPerByte());
+    // // assertEquals(1, decoder.maxCharsPerByte());
+    // assertEquals(decoder.averageCharsPerByte(), 0.5, 0.001);
+    // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+    // }
+
+    ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+        // no unmap byte buffer
+        return null;
+    }
+
+    ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+        // FIXME: different here, JDK can parse 0xd8d8
+        // ByteBuffer buffer = ByteBuffer.allocate(100);
+        // buffer.put((byte)0xd8);
+        // buffer.put((byte)0xd8);
+        // buffer.put(unibytes);
+        // buffer.flip();
+        // return buffer;
+        return null;
+    }
+
+    ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+        return null;
+    }
+
+    protected ByteBuffer getByteBuffer() {
+        return ByteBuffer.wrap(new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102,
+                0, 101, 0, 114, 0 });
+    }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetEncoderTest.java
new file mode 100644
index 0000000..1e9187d
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetEncoderTest.java
@@ -0,0 +1,109 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * TODO type def
+ */
+public class UTF16LECharsetEncoderTest extends CharsetEncoderTest {
+
+	// charset for utf-16le
+	private static final Charset CS = Charset.forName("utf-16le");
+
+	/*
+	 * @see CharsetEncoderTest#setUp()
+	 */
+	protected void setUp() throws Exception {
+		cs = CS;
+		specifiedReplacement = new byte[] { -3, -1 };
+
+		unibytes = new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0,
+				114, 0 };
+
+		// unibytesWithRep = new byte[] {(byte)0xfd, (byte)0xff, 32, 0, 98, 0,
+		// 117, 0, 102, 0, 102, 0, 101, 0, 114 ,0};
+
+		super.setUp();
+	}
+
+	/*
+	 * @see CharsetEncoderTest#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	public void testCharsetEncoderCharsetfloatfloat() {
+		// this constructor is invalid for UTF16LE CharsetEncoder
+	}
+
+	public void testCanEncodechar() throws CharacterCodingException {
+		// normal case for utfCS
+		assertTrue(encoder.canEncode('\u0077'));
+		assertTrue(encoder.canEncode('\uc2a3'));
+
+		// for non-mapped char
+		assertTrue(encoder.canEncode('\uc2c0'));
+	}
+
+	public void testCanEncodeCharSequence() {
+		// normal case for utfCS
+		assertTrue(encoder.canEncode("\u0077"));
+		assertTrue(encoder.canEncode("\uc2a3"));
+
+		// for non-mapped char
+		assertTrue(encoder.canEncode("\uc2c0"));
+
+		// surrogate char for unicode
+		// 1st byte: d800-dbff
+		// 2nd byte: dc00-dfff
+		// valid surrogate pair
+		assertTrue(encoder.canEncode("\ud800\udc00"));
+		// invalid surrogate pair
+		assertFalse(encoder.canEncode("\ud800\udb00"));
+	}
+
+	public void testSpecificDefaultValue() {
+		assertEquals(2, encoder.averageBytesPerChar(), 0.001);
+		assertEquals(2, encoder.maxBytesPerChar(), 0.001);
+	}
+
+	CharBuffer getMalformedCharBuffer() {
+		return CharBuffer.wrap("\ud800 buffer");
+	}
+
+	CharBuffer getUnmapCharBuffer() {
+		return null;
+	}
+
+	CharBuffer getExceptionCharBuffer() {
+		return null;
+	}
+
+	protected byte[] getIllegalByteArray() {
+	  return new byte[] { (byte)0x00, (byte)0xd8, (byte)0x00, (byte)0xdb };
+	}
+
+	protected byte[] getLegalByteArray() {
+		return new byte[] { (byte) 0xd8, 0x00 };
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetTest.java
new file mode 100644
index 0000000..d795773
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetTest.java
@@ -0,0 +1,54 @@
+/* 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 tests.api.java.nio.charset;
+
+/**
+ * Test UTF-16LE.
+ */
+public class UTF16LECharsetTest extends AbstractCharsetTestCase {
+
+	/**
+	 * Constructor.
+	 */
+	public UTF16LECharsetTest(String arg0) {
+		super(arg0, "UTF-16LE", new String[] { "UTF_16LE", "X-UTF-16LE" },
+				true, true);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+	 */
+	public void testEncode_Normal() {
+		String input = "ab\u5D14\u654F";
+		byte[] output = new byte[] { 97, 0, 98, 0, 20, 93, 79, 101 };
+		internalTestEncode(input, output);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+	 */
+	public void testDecode_Normal() {
+		byte[] input = new byte[] { 97, 0, 98, 0, 20, 93, 79, 101 };
+		char[] output = "ab\u5D14\u654F".toCharArray();
+		internalTestDecode(input, output);
+	}
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF8CharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF8CharsetTest.java
new file mode 100644
index 0000000..8ab8b5c
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF8CharsetTest.java
@@ -0,0 +1,62 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Test UTF-8 charset.
+ */
+public class UTF8CharsetTest extends AbstractCharsetTestCase {
+
+	/**
+	 * Constructor for UTF8CharsetTest.
+	 * 
+	 */
+	public UTF8CharsetTest(String arg0) {
+		super(arg0, "UTF-8", new String[] { "UTF8" }, true, true);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+	 */
+	public void testDecode_Normal() {
+		byte[] input = new byte[] { 97, 98, -27, -76, -108, -26, -107, -113 };
+		char[] output = "ab\u5D14\u654F".toCharArray();
+		internalTestDecode(input, output);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+	 */
+	public void testEncode_Normal() {
+		String input = "ab\u5D14\u654F";
+		byte[] output = new byte[] { 97, 98, -27, -76, -108, -26, -107, -113 };
+		internalTestEncode(input, output);
+	}
+	
+    public void test_surrogate() throws UnsupportedEncodingException {
+        // U+1D11E: MUSICAL SYMBOL G CLEF
+        String s = new StringBuilder().appendCodePoint(0x1D11E).toString();
+        byte utf8[] = s.getBytes("UTF-8");
+        assertEquals(s, new String(utf8, 0, utf8.length, "UTF-8"));
+    }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetDecoderTest.java
new file mode 100644
index 0000000..b8ed9fd
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetDecoderTest.java
@@ -0,0 +1,76 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * test utf-8 decoder
+ */
+public class UTFCharsetDecoderTest extends CharsetDecoderTest {
+
+    protected void setUp() throws Exception {
+        cs = Charset.forName("utf-8");
+        super.setUp();
+    }
+
+    /*
+     * @see CharsetDecoderTest#tearDown()
+     */
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    // FIXME: give up this tests
+    // public void testDefaultCharsPerByte(){
+    // assertEquals(decoder.averageCharsPerByte(), 0.333, 0.001);
+    // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+    // // assertEquals(1, decoder.averageCharsPerByte());
+    // // assertEquals(1, decoder.maxCharsPerByte());
+    // }
+
+    ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+        return null;
+    }
+
+    ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+        ByteBuffer buffer = ByteBuffer.allocate(getByteBuffer().remaining() + 1);
+        buffer.put((byte) 0xd8);
+        buffer.put(getByteBuffer());
+        buffer.flip();
+        return buffer;
+    }
+
+    ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+        return null;
+    }
+
+    protected String getString() {
+        return " buffer \u041c\u0430\u0441\u044e\u043b\u044f \u611b";
+    }
+
+    protected ByteBuffer getByteBuffer() {
+        return ByteBuffer.wrap(new byte[] { 32, 98, 117, 102, 102, 101, 114,
+                32, (byte) 0xd0, (byte) 0x9c, (byte) 0xd0, (byte) 0xb0,
+                (byte) 0xd1, (byte) 0x81, (byte) 0xd1, (byte) 0x8e,
+                (byte) 0xd0, (byte) 0xbb, (byte) 0xd1, (byte) 0x8f, 32,
+                (byte) 0xe6, (byte) 0x84, (byte) 0x9b });
+    }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java
new file mode 100644
index 0000000..798a048
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java
@@ -0,0 +1,98 @@
+/* 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 tests.api.java.nio.charset;
+
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * test case specific activity of utf-8 charset encoder
+ */
+public class UTFCharsetEncoderTest extends CharsetEncoderTest {
+
+	// charset for UTF-8
+	private static final Charset CS = Charset.forName("utf-8");
+
+	/*
+	 * @see CharsetEncoderTest#setUp()
+	 */
+	protected void setUp() throws Exception {
+		cs = CS;
+		specifiedReplacement = new byte[] { 63 };
+		super.setUp();
+	}
+
+	/*
+	 * @see CharsetEncoderTest#tearDown()
+	 */
+	protected void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	public void testCanEncodechar() throws CharacterCodingException {
+		// normal case for utfCS
+		assertTrue(encoder.canEncode('\u0077'));
+		assertTrue(encoder.canEncode('\uc2a3'));
+
+		// for non-mapped char
+		assertTrue(encoder.canEncode('\uc2c0'));
+	}
+
+	public void testCanEncodeCharSequence() {
+		// normal case for utfCS
+		assertTrue(encoder.canEncode("\u0077"));
+		assertTrue(encoder.canEncode("\uc2a3"));
+
+		// for non-mapped char
+		assertTrue(encoder.canEncode("\uc2c0"));
+
+		// surrogate char for unicode
+		// 1st byte: d800-dbff
+		// 2nd byte: dc00-dfff
+		// valid surrogate pair
+		assertTrue(encoder.canEncode("\ud800\udc00"));
+		// invalid surrogate pair
+		assertFalse(encoder.canEncode("\ud800\udb00"));
+	}
+
+	public void testSpecificDefaultValue() {
+		assertEquals(1.1, encoder.averageBytesPerChar(), 0.0001);
+		// assertEquals(2, encoder.averageBytesPerChar(), 0.0001);
+		assertEquals(4, encoder.maxBytesPerChar(), 0);
+		// assertEquals(3, encoder.maxBytesPerChar(), 0);
+	}
+
+	CharBuffer getMalformedCharBuffer() {
+		return CharBuffer.wrap("\ud800 buffer");
+	}
+
+	CharBuffer getUnmapCharBuffer() {
+		return null;
+	}
+
+	CharBuffer getExceptionCharBuffer() {
+		return null;
+	}
+
+	protected byte[] getIllegalByteArray() {
+		return new byte[] { (byte) 0xd8, (byte) 0x00 };
+	}
+
+	protected void assertFlushed() {
+	}
+}
diff --git a/include/ScopedBytes.h b/include/ScopedBytes.h
deleted file mode 100644
index cb2614b..0000000
--- a/include/ScopedBytes.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2010 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_BYTES_H_included
-#define SCOPED_BYTES_H_included
-
-#include "JNIHelp.h"
-
-/**
- * ScopedBytesRO and ScopedBytesRW attempt to paper over the differences between byte[]s and
- * ByteBuffers. This in turn helps paper over the differences between non-direct ByteBuffers backed
- * by byte[]s, direct ByteBuffers backed by bytes[]s, and direct ByteBuffers not backed by byte[]s.
- * (On Android, this last group only contains MappedByteBuffers.)
- */
-template<bool readOnly>
-class ScopedBytes {
-public:
-    ScopedBytes(JNIEnv* env, jobject object)
-    : mEnv(env), mObject(object), mByteArray(NULL), mPtr(NULL)
-    {
-        if (mObject == NULL) {
-            jniThrowNullPointerException(mEnv, NULL);
-        } else if (mEnv->IsInstanceOf(mObject, JniConstants::byteArrayClass)) {
-            mByteArray = reinterpret_cast<jbyteArray>(mObject);
-            mPtr = mEnv->GetByteArrayElements(mByteArray, NULL);
-        } else {
-            mPtr = reinterpret_cast<jbyte*>(mEnv->GetDirectBufferAddress(mObject));
-        }
-    }
-
-    ~ScopedBytes() {
-        if (mByteArray != NULL) {
-            mEnv->ReleaseByteArrayElements(mByteArray, mPtr, readOnly ? JNI_ABORT : 0);
-        }
-    }
-
-private:
-    JNIEnv* mEnv;
-    jobject mObject;
-    jbyteArray mByteArray;
-
-protected:
-    jbyte* mPtr;
-
-private:
-    // Disallow copy and assignment.
-    ScopedBytes(const ScopedBytes&);
-    void operator=(const ScopedBytes&);
-};
-
-class ScopedBytesRO : public ScopedBytes<true> {
-public:
-    ScopedBytesRO(JNIEnv* env, jobject object) : ScopedBytes<true>(env, object) {}
-    const jbyte* get() const {
-        return mPtr;
-    }
-};
-
-class ScopedBytesRW : public ScopedBytes<false> {
-public:
-    ScopedBytesRW(JNIEnv* env, jobject object) : ScopedBytes<false>(env, object) {}
-    jbyte* get() {
-        return mPtr;
-    }
-};
-
-#endif  // SCOPED_BYTES_H_included
diff --git a/include/ScopedFd.h b/include/ScopedFd.h
deleted file mode 100644
index d2b7935..0000000
--- a/include/ScopedFd.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SCOPED_FD_H_included
-#define SCOPED_FD_H_included
-
-#include <unistd.h>
-
-// A smart pointer that closes the given fd on going out of scope.
-// Use this when the fd is incidental to the purpose of your function,
-// but needs to be cleaned up on exit.
-class ScopedFd {
-public:
-    explicit ScopedFd(int fd) : fd(fd) {
-    }
-
-    ~ScopedFd() {
-        close(fd);
-    }
-
-    int get() const {
-        return fd;
-    }
-
-private:
-    int fd;
-
-    // Disallow copy and assignment.
-    ScopedFd(const ScopedFd&);
-    void operator=(const ScopedFd&);
-};
-
-#endif  // SCOPED_FD_H_included
diff --git a/include/ScopedLocalFrame.h b/include/ScopedLocalFrame.h
deleted file mode 100644
index 35b6ad8..0000000
--- a/include/ScopedLocalFrame.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010 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_LOCAL_FRAME_H_included
-#define SCOPED_LOCAL_FRAME_H_included
-
-#include "JNIHelp.h"
-
-class ScopedLocalFrame {
-public:
-    ScopedLocalFrame(JNIEnv* env) : mEnv(env) {
-        mEnv->PushLocalFrame(128);
-    }
-
-    ~ScopedLocalFrame() {
-        mEnv->PopLocalFrame(NULL);
-    }
-
-private:
-    JNIEnv* mEnv;
-
-    // Disallow copy and assignment.
-    ScopedLocalFrame(const ScopedLocalFrame&);
-    void operator=(const ScopedLocalFrame&);
-};
-
-#endif  // SCOPED_LOCAL_FRAME_H_included
diff --git a/include/ScopedLocalRef.h b/include/ScopedLocalRef.h
deleted file mode 100644
index 71d5776..0000000
--- a/include/ScopedLocalRef.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010 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_LOCAL_REF_H_included
-#define SCOPED_LOCAL_REF_H_included
-
-#include "jni.h"
-
-#include <stddef.h>
-
-// A smart pointer that deletes a JNI local reference when it goes out of scope.
-template<typename T>
-class ScopedLocalRef {
-public:
-    ScopedLocalRef(JNIEnv* env, T localRef) : mEnv(env), mLocalRef(localRef) {
-    }
-
-    ~ScopedLocalRef() {
-        reset();
-    }
-
-    void reset(T ptr = NULL) {
-        if (ptr != mLocalRef) {
-            if (mLocalRef != NULL) {
-                mEnv->DeleteLocalRef(mLocalRef);
-            }
-            mLocalRef = ptr;
-        }
-    }
-
-    T release() __attribute__((warn_unused_result)) {
-        T localRef = mLocalRef;
-        mLocalRef = NULL;
-        return localRef;
-    }
-
-    T get() const {
-        return mLocalRef;
-    }
-
-private:
-    JNIEnv* mEnv;
-    T mLocalRef;
-
-    // Disallow copy and assignment.
-    ScopedLocalRef(const ScopedLocalRef&);
-    void operator=(const ScopedLocalRef&);
-};
-
-#endif  // SCOPED_LOCAL_REF_H_included
diff --git a/include/ScopedPrimitiveArray.h b/include/ScopedPrimitiveArray.h
deleted file mode 100644
index f6626b2..0000000
--- a/include/ScopedPrimitiveArray.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2010 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_PRIMITIVE_ARRAY_H_included
-#define SCOPED_PRIMITIVE_ARRAY_H_included
-
-#include "JNIHelp.h"
-
-// ScopedBooleanArrayRO, ScopedByteArrayRO, ScopedCharArrayRO, ScopedDoubleArrayRO,
-// ScopedFloatArrayRO, ScopedIntArrayRO, ScopedLongArrayRO, and ScopedShortArrayRO provide
-// convenient read-only access to Java arrays from JNI code. This is cheaper than read-write
-// access and should be used by default.
-#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(PRIMITIVE_TYPE, NAME) \
-    class Scoped ## NAME ## ArrayRO { \
-    public: \
-        Scoped ## NAME ## ArrayRO(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
-        : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
-            if (mJavaArray == NULL) { \
-                jniThrowNullPointerException(mEnv, NULL); \
-            } else { \
-                mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
-            } \
-        } \
-        ~Scoped ## NAME ## ArrayRO() { \
-            if (mRawArray) { \
-                mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, JNI_ABORT); \
-            } \
-        } \
-        const PRIMITIVE_TYPE* get() const { return mRawArray; } \
-        PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
-        const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
-        size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
-    private: \
-        JNIEnv* mEnv; \
-        PRIMITIVE_TYPE ## Array mJavaArray; \
-        PRIMITIVE_TYPE* mRawArray; \
-        Scoped ## NAME ## ArrayRO(const Scoped ## NAME ## ArrayRO&); \
-        void operator=(const Scoped ## NAME ## ArrayRO&); \
-    }
-
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jboolean, Boolean);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jbyte, Byte);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jchar, Char);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jdouble, Double);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jfloat, Float);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jint, Int);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jlong, Long);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short);
-
-#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO
-
-// ScopedBooleanArrayRW, ScopedByteArrayRW, ScopedCharArrayRW, ScopedDoubleArrayRW,
-// ScopedFloatArrayRW, ScopedIntArrayRW, ScopedLongArrayRW, and ScopedShortArrayRW provide
-// convenient read-write access to Java arrays from JNI code. These are more expensive,
-// since they entail a copy back onto the Java heap, and should only be used when necessary.
-#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(PRIMITIVE_TYPE, NAME) \
-    class Scoped ## NAME ## ArrayRW { \
-    public: \
-        Scoped ## NAME ## ArrayRW(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
-        : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
-            if (mJavaArray == NULL) { \
-                jniThrowNullPointerException(mEnv, NULL); \
-            } else { \
-                mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
-            } \
-        } \
-        ~Scoped ## NAME ## ArrayRW() { \
-            if (mRawArray) { \
-                mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, 0); \
-            } \
-        } \
-        const PRIMITIVE_TYPE* get() const { return mRawArray; } \
-        PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
-        const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
-        PRIMITIVE_TYPE* get() { return mRawArray; } \
-        PRIMITIVE_TYPE& operator[](size_t n) { return mRawArray[n]; } \
-        size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
-    private: \
-        JNIEnv* mEnv; \
-        PRIMITIVE_TYPE ## Array mJavaArray; \
-        PRIMITIVE_TYPE* mRawArray; \
-        Scoped ## NAME ## ArrayRW(const Scoped ## NAME ## ArrayRW&); \
-        void operator=(const Scoped ## NAME ## ArrayRW&); \
-    }
-
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jboolean, Boolean);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jbyte, Byte);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jchar, Char);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jdouble, Double);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jfloat, Float);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jint, Int);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jlong, Long);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jshort, Short);
-
-#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW
-
-#endif  // SCOPED_PRIMITIVE_ARRAY_H_included
diff --git a/include/ScopedStringChars.h b/include/ScopedStringChars.h
deleted file mode 100644
index b59b786..0000000
--- a/include/ScopedStringChars.h
+++ /dev/null
@@ -1,51 +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.
- */
-
-#ifndef SCOPED_STRING_CHARS_H_included
-#define SCOPED_STRING_CHARS_H_included
-
-#include "JNIHelp.h"
-
-// A smart pointer that provides access to a jchar* given a JNI jstring.
-class ScopedStringChars {
-public:
-    ScopedStringChars(JNIEnv* env, jstring s) : mEnv(env), mString(s), mSize(0) {
-        mChars = env->GetStringChars(mString, NULL);
-        if (mChars != NULL) {
-            mSize = env->GetStringLength(mString);
-        }
-    }
-
-    ~ScopedStringChars() {
-        mEnv->ReleaseStringChars(mString, mChars);
-    }
-
-    const jchar* get() const { return mChars; }
-    const jchar& operator[](size_t n) const { return mChars[n]; }
-    size_t size() const { return mSize; }
-
-private:
-    JNIEnv* mEnv;
-    jstring mString;
-    const jchar* mChars;
-    size_t mSize;
-
-    // Disallow copy and assignment.
-    ScopedStringChars(const ScopedStringChars&);
-    void operator=(const ScopedStringChars&);
-};
-
-#endif  // SCOPED_STRING_CHARS_H_included
diff --git a/include/ScopedUtfChars.h b/include/ScopedUtfChars.h
deleted file mode 100644
index 7492a0c..0000000
--- a/include/ScopedUtfChars.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2010 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_UTF_CHARS_H_included
-#define SCOPED_UTF_CHARS_H_included
-
-#include "JNIHelp.h"
-#include <string.h>
-
-// A smart pointer that provides read-only access to a Java string's UTF chars.
-// Unlike GetStringUTFChars, we throw NullPointerException rather than abort if
-// passed a null jstring, and c_str will return NULL.
-// This makes the correct idiom very simple:
-//
-//   ScopedUtfChars name(env, javaName);
-//   if (name.c_str() == NULL) {
-//       return NULL;
-//   }
-class ScopedUtfChars {
-public:
-    ScopedUtfChars(JNIEnv* env, jstring s)
-    : mEnv(env), mString(s)
-    {
-        if (s == NULL) {
-            mUtfChars = NULL;
-            jniThrowNullPointerException(env, NULL);
-        } else {
-            mUtfChars = env->GetStringUTFChars(s, NULL);
-        }
-    }
-
-    ~ScopedUtfChars() {
-        if (mUtfChars) {
-            mEnv->ReleaseStringUTFChars(mString, mUtfChars);
-        }
-    }
-
-    const char* c_str() const {
-        return mUtfChars;
-    }
-
-    size_t size() const {
-        return strlen(mUtfChars);
-    }
-
-    // Element access.
-    const char& operator[](size_t n) const {
-        return mUtfChars[n];
-    }
-
-private:
-    JNIEnv* mEnv;
-    jstring mString;
-    const char* mUtfChars;
-
-    // Disallow copy and assignment.
-    ScopedUtfChars(const ScopedUtfChars&);
-    void operator=(const ScopedUtfChars&);
-};
-
-#endif  // SCOPED_UTF_CHARS_H_included
diff --git a/include/UniquePtr.h b/include/UniquePtr.h
deleted file mode 100644
index 31db377..0000000
--- a/include/UniquePtr.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (C) 2010 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 UNIQUE_PTR_H_included
-#define UNIQUE_PTR_H_included
-
-#include <cstdlib> // For NULL.
-
-// Default deleter for pointer types.
-template <typename T>
-struct DefaultDelete {
-    enum { type_must_be_complete = sizeof(T) };
-    DefaultDelete() {}
-    void operator()(T* p) const {
-        delete p;
-    }
-};
-
-// Default deleter for array types.
-template <typename T>
-struct DefaultDelete<T[]> {
-    enum { type_must_be_complete = sizeof(T) };
-    void operator()(T* p) const {
-        delete[] p;
-    }
-};
-
-// A smart pointer that deletes the given pointer on destruction.
-// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
-// and boost::scoped_array).
-// Named to be in keeping with Android style but also to avoid
-// collision with any other implementation, until we can switch over
-// to unique_ptr.
-// Use thus:
-//   UniquePtr<C> c(new C);
-template <typename T, typename D = DefaultDelete<T> >
-class UniquePtr {
-public:
-    // Construct a new UniquePtr, taking ownership of the given raw pointer.
-    explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
-    }
-
-    ~UniquePtr() {
-        reset();
-    }
-
-    // Accessors.
-    T& operator*() const { return *mPtr; }
-    T* operator->() const { return mPtr; }
-    T* get() const { return mPtr; }
-
-    // Returns the raw pointer and hands over ownership to the caller.
-    // The pointer will not be deleted by UniquePtr.
-    T* release() __attribute__((warn_unused_result)) {
-        T* result = mPtr;
-        mPtr = NULL;
-        return result;
-    }
-
-    // Takes ownership of the given raw pointer.
-    // If this smart pointer previously owned a different raw pointer, that
-    // raw pointer will be freed.
-    void reset(T* ptr = NULL) {
-        if (ptr != mPtr) {
-            D()(mPtr);
-            mPtr = ptr;
-        }
-    }
-
-private:
-    // The raw pointer.
-    T* mPtr;
-
-    // Comparing unique pointers is probably a mistake, since they're unique.
-    template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
-    template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
-
-    // Disallow copy and assignment.
-    UniquePtr(const UniquePtr&);
-    void operator=(const UniquePtr&);
-};
-
-// Partial specialization for array types. Like std::unique_ptr, this removes
-// operator* and operator-> but adds operator[].
-template <typename T, typename D>
-class UniquePtr<T[], D> {
-public:
-    explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
-    }
-
-    ~UniquePtr() {
-        reset();
-    }
-
-    T& operator[](size_t i) const {
-        return mPtr[i];
-    }
-    T* get() const { return mPtr; }
-
-    T* release() __attribute__((warn_unused_result)) {
-        T* result = mPtr;
-        mPtr = NULL;
-        return result;
-    }
-
-    void reset(T* ptr = NULL) {
-        if (ptr != mPtr) {
-            D()(mPtr);
-            mPtr = ptr;
-        }
-    }
-
-private:
-    T* mPtr;
-
-    // Disallow copy and assignment.
-    UniquePtr(const UniquePtr&);
-    void operator=(const UniquePtr&);
-};
-
-#if UNIQUE_PTR_TESTS
-
-// Run these tests with:
-// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
-
-#include <stdio.h>
-
-static void assert(bool b) {
-    if (!b) {
-        fprintf(stderr, "FAIL\n");
-        abort();
-    }
-    fprintf(stderr, "OK\n");
-}
-static int cCount = 0;
-struct C {
-    C() { ++cCount; }
-    ~C() { --cCount; }
-};
-static bool freed = false;
-struct Freer {
-    void operator()(int* p) {
-        assert(*p == 123);
-        free(p);
-        freed = true;
-    }
-};
-
-int main(int argc, char* argv[]) {
-    //
-    // UniquePtr<T> tests...
-    //
-
-    // Can we free a single object?
-    {
-        UniquePtr<C> c(new C);
-        assert(cCount == 1);
-    }
-    assert(cCount == 0);
-    // Does release work?
-    C* rawC;
-    {
-        UniquePtr<C> c(new C);
-        assert(cCount == 1);
-        rawC = c.release();
-    }
-    assert(cCount == 1);
-    delete rawC;
-    // Does reset work?
-    {
-        UniquePtr<C> c(new C);
-        assert(cCount == 1);
-        c.reset(new C);
-        assert(cCount == 1);
-    }
-    assert(cCount == 0);
-
-    //
-    // UniquePtr<T[]> tests...
-    //
-
-    // Can we free an array?
-    {
-        UniquePtr<C[]> cs(new C[4]);
-        assert(cCount == 4);
-    }
-    assert(cCount == 0);
-    // Does release work?
-    {
-        UniquePtr<C[]> c(new C[4]);
-        assert(cCount == 4);
-        rawC = c.release();
-    }
-    assert(cCount == 4);
-    delete[] rawC;
-    // Does reset work?
-    {
-        UniquePtr<C[]> c(new C[4]);
-        assert(cCount == 4);
-        c.reset(new C[2]);
-        assert(cCount == 2);
-    }
-    assert(cCount == 0);
-
-    //
-    // Custom deleter tests...
-    //
-    assert(!freed);
-    {
-        UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
-        *i = 123;
-    }
-    assert(freed);
-    return 0;
-}
-#endif
-
-#endif  // UNIQUE_PTR_H_included
diff --git a/json/src/main/java/org/json/JSONArray.java b/json/src/main/java/org/json/JSONArray.java
index a885125..f6801aa 100644
--- a/json/src/main/java/org/json/JSONArray.java
+++ b/json/src/main/java/org/json/JSONArray.java
@@ -16,8 +16,10 @@
 
 package org.json;
 
+import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
 
 // Note: this class was written without inspecting the non-free org.json sourcecode.
@@ -66,8 +68,11 @@
     /* Accept a raw type for API compatibility */
     public JSONArray(Collection copyFrom) {
         this();
-        Collection<?> copyFromTyped = (Collection<?>) copyFrom;
-        values.addAll(copyFromTyped);
+        if (copyFrom != null) {
+            for (Iterator it = copyFrom.iterator(); it.hasNext();) {
+                put(JSONObject.wrap(it.next()));
+            }
+        }
     }
 
     /**
@@ -104,6 +109,20 @@
     }
 
     /**
+     * Creates a new {@code JSONArray} with values from the given primitive array.
+     */
+    public JSONArray(Object array) throws JSONException {
+        if (!array.getClass().isArray()) {
+            throw new JSONException("Not a primitive array: " + array.getClass());
+        }
+        final int length = Array.getLength(array);
+        values = new ArrayList<Object>(length);
+        for (int i = 0; i < length; ++i) {
+            put(JSONObject.wrap(Array.get(array, i)));
+        }
+    }
+
+    /**
      * Returns the number of values in this array.
      */
     public int length() {
@@ -276,6 +295,17 @@
     }
 
     /**
+     * Removes and returns the value at {@code index}, or null if the array has no value
+     * at {@code index}.
+     */
+    public Object remove(int index) {
+        if (index < 0 || index >= values.size()) {
+            return null;
+        }
+        return values.remove(index);
+    }
+
+    /**
      * Returns the value at {@code index} if it exists and is a boolean or can
      * be coerced to a boolean.
      *
diff --git a/json/src/main/java/org/json/JSONObject.java b/json/src/main/java/org/json/JSONObject.java
index c2a656c..ae3b747 100644
--- a/json/src/main/java/org/json/JSONObject.java
+++ b/json/src/main/java/org/json/JSONObject.java
@@ -17,6 +17,7 @@
 package org.json;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -133,7 +134,7 @@
             if (key == null) {
                 throw new NullPointerException("key == null");
             }
-            nameValuePairs.put(key, entry.getValue());
+            nameValuePairs.put(key, wrap(entry.getValue()));
         }
     }
 
@@ -721,4 +722,54 @@
             throw new AssertionError();
         }
     }
+
+    /**
+     * Wraps the given object if necessary.
+     *
+     * <p>If the object is null or , returns {@link #NULL}.
+     * If the object is a {@code JSONArray} or {@code JSONObject}, no wrapping is necessary.
+     * If the object is {@code NULL}, no wrapping is necessary.
+     * If the object is an array or {@code Collection}, returns an equivalent {@code JSONArray}.
+     * If the object is a {@code Map}, returns an equivalent {@code JSONObject}.
+     * If the object is a primitive wrapper type or {@code String}, returns the object.
+     * Otherwise if the object is from a {@code java} package, returns the result of {@code toString}.
+     * If wrapping fails, returns null.
+     */
+    public static Object wrap(Object o) {
+        if (o == null) {
+            return NULL;
+        }
+        if (o instanceof JSONArray || o instanceof JSONObject) {
+            return o;
+        }
+        if (o.equals(NULL)) {
+            return o;
+        }
+        try {
+            if (o instanceof Collection) {
+                return new JSONArray((Collection) o);
+            } else if (o.getClass().isArray()) {
+                return new JSONArray(o);
+            }
+            if (o instanceof Map) {
+                return new JSONObject((Map) o);
+            }
+            if (o instanceof Boolean ||
+                o instanceof Byte ||
+                o instanceof Character ||
+                o instanceof Double ||
+                o instanceof Float ||
+                o instanceof Integer ||
+                o instanceof Long ||
+                o instanceof Short ||
+                o instanceof String) {
+                return o;
+            }
+            if (o.getClass().getPackage().getName().startsWith("java.")) {
+                return o.toString();
+            }
+        } catch (Exception ignored) {
+        }
+        return null;
+    }
 }
diff --git a/json/src/test/java/org/json/JSONArrayTest.java b/json/src/test/java/org/json/JSONArrayTest.java
index 1e72af2..52767db 100644
--- a/json/src/test/java/org/json/JSONArrayTest.java
+++ b/json/src/test/java/org/json/JSONArrayTest.java
@@ -17,6 +17,7 @@
 package org.json;
 
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import junit.framework.TestCase;
@@ -136,7 +137,7 @@
 
     public void testNulls() throws JSONException {
         JSONArray array = new JSONArray();
-        array.put(3, null);
+        array.put(3, (Collection) null);
         array.put(0, JSONObject.NULL);
         assertEquals(4, array.length());
         assertEquals("[null,null,null,null]", array.toString());
@@ -178,7 +179,7 @@
      */
     public void testParseNullYieldsJSONObjectNull() throws JSONException {
         JSONArray array = new JSONArray("[\"null\",null]");
-        array.put(null);
+        array.put((Collection) null);
         assertEquals("null", array.get(0));
         assertEquals(JSONObject.NULL, array.get(1));
         try {
@@ -296,7 +297,7 @@
 
     public void testJoin() throws JSONException {
         JSONArray array = new JSONArray();
-        array.put(null);
+        array.put((Collection) null);
         assertEquals("null", array.join(" & "));
         array.put("\"");
         assertEquals("null & \"\\\"\"", array.join(" & "));
@@ -345,7 +346,7 @@
 
         JSONArray values = new JSONArray();
         values.put(5.5d);
-        values.put(null);
+        values.put((Collection) null);
 
         // null values are stripped!
         JSONObject object = values.toJSONObject(keys);
@@ -538,4 +539,16 @@
         } catch (JSONException e) {
         }
     }
+
+    public void test_remove() throws Exception {
+        JSONArray a = new JSONArray();
+        assertEquals(null, a.remove(-1));
+        assertEquals(null, a.remove(0));
+
+        a.put("hello");
+        assertEquals(null, a.remove(-1));
+        assertEquals(null, a.remove(1));
+        assertEquals("hello", a.remove(0));
+        assertEquals(null, a.remove(0));
+    }
 }
diff --git a/json/src/test/java/org/json/JSONObjectTest.java b/json/src/test/java/org/json/JSONObjectTest.java
index e192b03..8abd88f 100644
--- a/json/src/test/java/org/json/JSONObjectTest.java
+++ b/json/src/test/java/org/json/JSONObjectTest.java
@@ -18,7 +18,9 @@
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -156,7 +158,7 @@
     public void testPutNullRemoves() throws JSONException {
         JSONObject object = new JSONObject();
         object.put("foo", "bar");
-        object.put("foo", null);
+        object.put("foo", (Collection) null);
         assertEquals(0, object.length());
         assertFalse(object.has("foo"));
         try {
@@ -734,7 +736,7 @@
         }
     }
 
-    public void testStringonstructorParseFail() {
+    public void testStringConstructorParseFail() {
         try {
             new JSONObject("{");
             fail();
@@ -813,7 +815,7 @@
     public void testNullValue() throws JSONException {
         JSONObject object = new JSONObject();
         object.put("foo", JSONObject.NULL);
-        object.put("bar", null);
+        object.put("bar", (Collection) null);
 
         // there are two ways to represent null; each behaves differently!
         assertTrue(object.has("foo"));
@@ -961,4 +963,34 @@
         } catch (JSONException e) {
         }
     }
+
+    public void test_wrap() throws Exception {
+        assertEquals(JSONObject.NULL, JSONObject.wrap(null));
+
+        JSONArray a = new JSONArray();
+        assertEquals(a, JSONObject.wrap(a));
+
+        JSONObject o = new JSONObject();
+        assertEquals(o, JSONObject.wrap(o));
+
+        assertEquals(JSONObject.NULL, JSONObject.wrap(JSONObject.NULL));
+
+        assertTrue(JSONObject.wrap(new byte[0]) instanceof JSONArray);
+        assertTrue(JSONObject.wrap(new ArrayList<String>()) instanceof JSONArray);
+        assertTrue(JSONObject.wrap(new HashMap<String, String>()) instanceof JSONObject);
+        assertTrue(JSONObject.wrap(Double.valueOf(0)) instanceof Double);
+        assertTrue(JSONObject.wrap("hello") instanceof String);
+        assertTrue(JSONObject.wrap(java.nio.channels.Selector.open()) instanceof String);
+    }
+
+    // https://code.google.com/p/android/issues/detail?id=55114
+    public void test_toString_listAsMapValue() throws Exception {
+        ArrayList<Object> list = new ArrayList<Object>();
+        list.add("a");
+        list.add(new ArrayList<String>());
+        HashMap<String, Object> map = new HashMap<String, Object>();
+        map.put("x", "l");
+        map.put("y", list);
+        assertEquals("{\"y\":[\"a\",[]],\"x\":\"l\"}", new JSONObject(map).toString());
+    }
 }
diff --git a/json/src/test/java/org/json/ParsingTest.java b/json/src/test/java/org/json/ParsingTest.java
index c38c367..641f5b9 100644
--- a/json/src/test/java/org/json/ParsingTest.java
+++ b/json/src/test/java/org/json/ParsingTest.java
@@ -261,6 +261,8 @@
                 result.put(key, canonicalize(object.get(key)));
             }
             return result;
+        } else if (input == null || input.equals(JSONObject.NULL)) {
+            return JSONObject.NULL;
         } else {
             return input;
         }
diff --git a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java b/libdvm/src/main/java/dalvik/system/BaseDexClassLoader.java
similarity index 100%
rename from dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
rename to libdvm/src/main/java/dalvik/system/BaseDexClassLoader.java
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/libdvm/src/main/java/dalvik/system/DexFile.java
similarity index 97%
rename from dalvik/src/main/java/dalvik/system/DexFile.java
rename to libdvm/src/main/java/dalvik/system/DexFile.java
index 8db3985..18b730b 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/libdvm/src/main/java/dalvik/system/DexFile.java
@@ -273,12 +273,6 @@
         int flags) throws IOException;
 
     /*
-     * Open a DEX file based on a {@code byte[]}. The value returned
-     * is a magic VM cookie. On failure, a RuntimeException is thrown.
-     */
-    native private static int openDexFile(byte[] fileContents);
-
-    /*
      * Close DEX file.
      */
     native private static void closeDexFile(int cookie);
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/libdvm/src/main/java/dalvik/system/DexPathList.java
similarity index 98%
rename from dalvik/src/main/java/dalvik/system/DexPathList.java
rename to libdvm/src/main/java/dalvik/system/DexPathList.java
index 3d9ee3e..a10e90e 100644
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ b/libdvm/src/main/java/dalvik/system/DexPathList.java
@@ -148,8 +148,7 @@
          *
          * This order was reversed prior to Gingerbread; see http://b/2933456.
          */
-        ArrayList<File> result = splitPaths(
-                path, System.getProperty("java.library.path", "."), true);
+        ArrayList<File> result = splitPaths(path, System.getProperty("java.library.path"), true);
         return result.toArray(new File[result.size()]);
     }
 
diff --git a/dalvik/src/main/java/dalvik/system/VMDebug.java b/libdvm/src/main/java/dalvik/system/VMDebug.java
similarity index 98%
rename from dalvik/src/main/java/dalvik/system/VMDebug.java
rename to libdvm/src/main/java/dalvik/system/VMDebug.java
index 8f40165..a80cfcc 100644
--- a/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/libdvm/src/main/java/dalvik/system/VMDebug.java
@@ -32,7 +32,7 @@
     /**
      * Specifies the default method trace data file name.
      *
-     * @deprecated only used in one place, which is unused and deprecated
+     * @deprecated Only used in one place, which is unused and deprecated.
      */
     @Deprecated
     static public final String DEFAULT_METHOD_TRACE_FILE_NAME = "/sdcard/dmtrace.trace";
@@ -140,7 +140,7 @@
      * Start method tracing with default name, size, and with <code>0</code>
      * flags.
      *
-     * @deprecated not used, not needed
+     * @deprecated Not used, not needed.
      */
     @Deprecated
     public static void startMethodTracing() {
diff --git a/dalvik/src/main/java/dalvik/system/VMRuntime.java b/libdvm/src/main/java/dalvik/system/VMRuntime.java
similarity index 100%
rename from dalvik/src/main/java/dalvik/system/VMRuntime.java
rename to libdvm/src/main/java/dalvik/system/VMRuntime.java
diff --git a/dalvik/src/main/java/dalvik/system/VMStack.java b/libdvm/src/main/java/dalvik/system/VMStack.java
similarity index 82%
rename from dalvik/src/main/java/dalvik/system/VMStack.java
rename to libdvm/src/main/java/dalvik/system/VMStack.java
index 9a2be23..bae1829 100644
--- a/dalvik/src/main/java/dalvik/system/VMStack.java
+++ b/libdvm/src/main/java/dalvik/system/VMStack.java
@@ -59,6 +59,22 @@
     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
diff --git a/luni/src/main/java/java/lang/Class.java b/libdvm/src/main/java/java/lang/Class.java
similarity index 95%
rename from luni/src/main/java/java/lang/Class.java
rename to libdvm/src/main/java/java/lang/Class.java
index f618b66..2f26688 100644
--- a/luni/src/main/java/java/lang/Class.java
+++ b/libdvm/src/main/java/java/lang/Class.java
@@ -32,6 +32,7 @@
 
 package java.lang;
 
+import com.android.dex.Dex;
 import dalvik.system.VMStack;
 import java.io.InputStream;
 import java.io.Serializable;
@@ -56,8 +57,9 @@
 import libcore.util.CollectionUtils;
 import libcore.util.EmptyArray;
 import org.apache.harmony.kernel.vm.StringUtils;
-import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
-import org.apache.harmony.luni.lang.reflect.Types;
+import libcore.reflect.AnnotationAccess;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.Types;
 
 /**
  * The in-memory representation of a Java class. This representation serves as
@@ -123,12 +125,39 @@
      */
     private transient String name;
 
+    private transient int dexTypeIndex;
+
     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();
+
+    /**
+     * The type index of this class in its own Dex, or 0 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.
+     *
+     * TODO: 0 is a valid index; this should be -1 if it is unknown
+     *
+     * @hide
+     */
+    public int getTypeIndex() {
+        int result = dexTypeIndex;
+        if (result == 0) {  // uncomputed => Dalvik
+            result = AnnotationAccess.computeTypeIndex(getDex(), this);
+            dexTypeIndex = result;
+        }
+        return result;
+    }
+
+    /**
      * Get the Signature attribute for this class.  Returns null if not found.
      */
     private String getSignatureAttribute() {
@@ -388,9 +417,11 @@
      * 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.
-     * @see #getDeclaredConstructor(Class[])
      */
     @SuppressWarnings("unchecked")
     public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException {
@@ -502,9 +533,10 @@
      * 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.
-     * @see #getConstructor(Class[])
      */
     @SuppressWarnings("unchecked")
     public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
@@ -578,11 +610,12 @@
      * 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}.
-     * @see #getMethod(String, Class[])
      */
     public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
             throws NoSuchMethodException {
@@ -774,14 +807,15 @@
      * 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.
-     * 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 finally the superclasses of C
-     * for a method with matching name.
+     *
+     * <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.
-     * @see #getDeclaredMethod(String, Class[])
      */
     public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException {
         Member member = getConstructorOrMethod(name, true, true, parameterTypes);
@@ -1215,4 +1249,17 @@
         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 getAnnotationDirectoryOffset() {
+        return AnnotationAccess.typeIndexToAnnotationDirectoryOffset(getDex(), getTypeIndex());
+    }
+
 }
diff --git a/luni/src/main/java/java/lang/ClassLoader.java b/libdvm/src/main/java/java/lang/ClassLoader.java
similarity index 98%
rename from luni/src/main/java/java/lang/ClassLoader.java
rename to libdvm/src/main/java/java/lang/ClassLoader.java
index c99d57c..c6a80913 100644
--- a/luni/src/main/java/java/lang/ClassLoader.java
+++ b/libdvm/src/main/java/java/lang/ClassLoader.java
@@ -218,13 +218,12 @@
      *             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)}
+     * @deprecated Use {@link #defineClass(String, byte[], int, int)} instead.
      */
     @Deprecated
     protected final Class<?> defineClass(byte[] classRep, int offset, int length)
             throws ClassFormatError {
-
-        return VMClassLoader.defineClass(this, classRep, offset, length);
+        throw new UnsupportedOperationException("can't load this type of class file");
     }
 
     /**
@@ -251,9 +250,7 @@
      */
     protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length)
             throws ClassFormatError {
-
-        // TODO Define a default ProtectionDomain on first use
-        return defineClass(className, classRep, offset, length, null);
+        throw new UnsupportedOperationException("can't load this type of class file");
     }
 
     /**
@@ -288,8 +285,7 @@
      */
     protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length,
             ProtectionDomain protectionDomain) throws java.lang.ClassFormatError {
-
-        return VMClassLoader.defineClass(this, className, classRep, offset, length);
+        throw new UnsupportedOperationException("can't load this type of class file");
     }
 
     /**
diff --git a/luni/src/main/java/java/lang/Daemons.java b/libdvm/src/main/java/java/lang/Daemons.java
similarity index 100%
rename from luni/src/main/java/java/lang/Daemons.java
rename to libdvm/src/main/java/java/lang/Daemons.java
diff --git a/luni/src/main/java/java/lang/Enum.java b/libdvm/src/main/java/java/lang/Enum.java
similarity index 100%
rename from luni/src/main/java/java/lang/Enum.java
rename to libdvm/src/main/java/java/lang/Enum.java
diff --git a/luni/src/main/java/java/lang/Object.java b/libdvm/src/main/java/java/lang/Object.java
similarity index 100%
rename from luni/src/main/java/java/lang/Object.java
rename to libdvm/src/main/java/java/lang/Object.java
diff --git a/luni/src/main/java/java/lang/String.java b/libdvm/src/main/java/java/lang/String.java
similarity index 98%
rename from luni/src/main/java/java/lang/String.java
rename to libdvm/src/main/java/java/lang/String.java
index 89691e7..27469f0 100644
--- a/luni/src/main/java/java/lang/String.java
+++ b/libdvm/src/main/java/java/lang/String.java
@@ -573,7 +573,12 @@
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0} or {@code index >= length()}.
      */
-    public native char charAt(int index);
+    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);
@@ -791,7 +796,7 @@
      * @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)}
+     * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)} instead.
      */
     @Deprecated
     public void getBytes(int start, int end, byte[] data, int index) {
@@ -1077,7 +1082,9 @@
      *
      * @since 1.6
      */
-    public native boolean isEmpty();
+    public boolean isEmpty() {
+        return count == 0;
+    }
 
     /**
      * Returns the last index of the code point {@code c}, or -1.
@@ -1197,11 +1204,11 @@
     }
 
     /**
-     * Returns the size of this string.
-     *
-     * @return the number of characters in this string.
+     * Returns the number of characters in this string.
      */
-    public native int length();
+    public int length() {
+        return count;
+    }
 
     /**
      * Compares the specified string to this string and compares the specified
@@ -1360,10 +1367,14 @@
         // The empty target matches at the start and end and between each character.
         int targetLength = targetString.length();
         if (targetLength == 0) {
-            int resultLength = (count + 2) * replacementString.length();
+            // 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);
-            for (int i = offset; i < count; ++i) {
+            int end = offset + count;
+            for (int i = offset; i != end; ++i) {
                 result.append(value[i]);
                 result.append(replacementString);
             }
@@ -1465,9 +1476,9 @@
     }
 
     /**
-     * Copies the characters in this string to a character array.
-     *
-     * @return a character array containing the characters of this string.
+     * 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];
diff --git a/luni/src/main/java/java/lang/Thread.java b/libdvm/src/main/java/java/lang/Thread.java
similarity index 99%
rename from luni/src/main/java/java/lang/Thread.java
rename to libdvm/src/main/java/java/lang/Thread.java
index cc0975f..ee4bdbe 100644
--- a/luni/src/main/java/java/lang/Thread.java
+++ b/libdvm/src/main/java/java/lang/Thread.java
@@ -1034,7 +1034,7 @@
      * resumed if it was suspended and awakened if it was sleeping, so that it
      * can proceed to throw ThreadDeath.
      *
-     * @deprecated because stopping a thread in this manner is unsafe and can
+     * @deprecated Stopping a thread in this manner is unsafe and can
      * leave your application and the VM in an unpredictable state.
      */
     @Deprecated
@@ -1044,7 +1044,7 @@
 
     /**
      * Throws {@code UnsupportedOperationException}.
-     * @deprecated because stopping a thread in this manner is unsafe and can
+     * @deprecated Stopping a thread in this manner is unsafe and can
      * leave your application and the VM in an unpredictable state.
      */
     @Deprecated
diff --git a/luni/src/main/java/java/lang/ThreadGroup.java b/libdvm/src/main/java/java/lang/ThreadGroup.java
similarity index 98%
rename from luni/src/main/java/java/lang/ThreadGroup.java
rename to libdvm/src/main/java/java/lang/ThreadGroup.java
index e99e99f..7fc6b72 100644
--- a/luni/src/main/java/java/lang/ThreadGroup.java
+++ b/libdvm/src/main/java/java/lang/ThreadGroup.java
@@ -176,7 +176,7 @@
      * @param b Used to control low memory implicit suspension
      * @return {@code true} (always)
      *
-     * @deprecated Required deprecated method suspend().
+     * @deprecated Required deprecated method {@link #suspend()}.
      */
     @Deprecated
     public boolean allowThreadSuspension(boolean b) {
@@ -533,7 +533,7 @@
      * @see Thread#resume
      * @see #suspend
      *
-     * @deprecated Requires deprecated method Thread.resume().
+     * @deprecated Requires deprecated method {@link Thread#resume()}.
      */
     @SuppressWarnings("deprecation")
     @Deprecated
@@ -600,7 +600,7 @@
      * @see Thread#stop(Throwable)
      * @see ThreadDeath
      *
-     * @deprecated Requires deprecated method Thread.stop().
+     * @deprecated Requires deprecated method {@link Thread#stop()}.
      */
     @SuppressWarnings("deprecation")
     @Deprecated
@@ -638,7 +638,7 @@
      * @see Thread#suspend
      * @see #resume
      *
-     * @deprecated Requires deprecated method Thread.suspend().
+     * @deprecated Requires deprecated method {@link Thread#suspend()}.
      */
     @SuppressWarnings("deprecation")
     @Deprecated
diff --git a/luni/src/main/java/java/lang/VMClassLoader.java b/libdvm/src/main/java/java/lang/VMClassLoader.java
similarity index 91%
rename from luni/src/main/java/java/lang/VMClassLoader.java
rename to libdvm/src/main/java/java/lang/VMClassLoader.java
index 8604360..d7162c6 100644
--- a/luni/src/main/java/java/lang/VMClassLoader.java
+++ b/libdvm/src/main/java/java/lang/VMClassLoader.java
@@ -75,12 +75,6 @@
 
     native static Class getPrimitiveClass(char type);
 
-    native static Class defineClass(ClassLoader cl, String name, byte[] data, int offset, int len)
-            throws ClassFormatError;
-
-    native static Class defineClass(ClassLoader cl, byte[] data, int offset, int len)
-            throws ClassFormatError;
-
     native static Class findLoadedClass(ClassLoader cl, String name);
 
     /**
diff --git a/luni/src/main/java/java/lang/VMThread.java b/libdvm/src/main/java/java/lang/VMThread.java
similarity index 100%
rename from luni/src/main/java/java/lang/VMThread.java
rename to libdvm/src/main/java/java/lang/VMThread.java
diff --git a/luni/src/main/java/java/lang/reflect/AccessibleObject.java b/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
similarity index 100%
rename from luni/src/main/java/java/lang/reflect/AccessibleObject.java
rename to libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
diff --git a/luni/src/main/java/java/lang/reflect/Constructor.java b/libdvm/src/main/java/java/lang/reflect/Constructor.java
similarity index 97%
rename from luni/src/main/java/java/lang/reflect/Constructor.java
rename to libdvm/src/main/java/java/lang/reflect/Constructor.java
index 9a0e03c..531f269 100644
--- a/luni/src/main/java/java/lang/reflect/Constructor.java
+++ b/libdvm/src/main/java/java/lang/reflect/Constructor.java
@@ -35,9 +35,9 @@
 import java.lang.annotation.Annotation;
 import libcore.util.EmptyArray;
 import org.apache.harmony.kernel.vm.StringUtils;
-import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
-import org.apache.harmony.luni.lang.reflect.ListOfTypes;
-import org.apache.harmony.luni.lang.reflect.Types;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.ListOfTypes;
+import libcore.reflect.Types;
 
 /**
  * This class represents a constructor. Information about the constructor can be
@@ -74,6 +74,8 @@
 
     int slot;
 
+    private int methodDexIndex;
+
     /**
      * Prevent this class from being instantiated.
      */
@@ -94,11 +96,17 @@
      * @param slot
      *            the slot of the constructor inside the VM class structure
      */
-    private Constructor (Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot){
+    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() {
diff --git a/luni/src/main/java/java/lang/reflect/Field.java b/libdvm/src/main/java/java/lang/reflect/Field.java
similarity index 98%
rename from luni/src/main/java/java/lang/reflect/Field.java
rename to libdvm/src/main/java/java/lang/reflect/Field.java
index 0aacb11..fa8e5e7 100644
--- a/luni/src/main/java/java/lang/reflect/Field.java
+++ b/libdvm/src/main/java/java/lang/reflect/Field.java
@@ -35,8 +35,8 @@
 import java.lang.annotation.Annotation;
 import java.util.Comparator;
 import org.apache.harmony.kernel.vm.StringUtils;
-import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
-import org.apache.harmony.luni.lang.reflect.Types;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.Types;
 
 /**
  * This class represents a field. Information about the field can be accessed,
@@ -73,6 +73,8 @@
 
     private int slot;
 
+    private final int fieldDexIndex;
+
     private static final char TYPE_BOOLEAN = 'Z';
 
     private static final char TYPE_BYTE = 'B';
@@ -89,25 +91,20 @@
 
     private static final char TYPE_DOUBLE = 'D';
 
-    /**
-     * Construct a clone of the given instance.
-     *
-     * @param orig non-null; the original instance to clone
-     */
-    /*package*/ Field(Field orig) {
-        this(orig.declaringClass, orig.type, orig.name, orig.slot);
-
-        // Copy the accessible flag.
-        if (orig.flag) {
-            this.flag = true;
-        }
-    }
-
-    private Field(Class<?> declaringClass, Class<?> type, String name, int slot) {
+    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() {
diff --git a/luni/src/main/java/java/lang/reflect/Method.java b/libdvm/src/main/java/java/lang/reflect/Method.java
similarity index 96%
rename from luni/src/main/java/java/lang/reflect/Method.java
rename to libdvm/src/main/java/java/lang/reflect/Method.java
index b2f970a..028b9ca 100644
--- a/luni/src/main/java/java/lang/reflect/Method.java
+++ b/libdvm/src/main/java/java/lang/reflect/Method.java
@@ -37,9 +37,9 @@
 import java.util.Comparator;
 import libcore.util.EmptyArray;
 import org.apache.harmony.kernel.vm.StringUtils;
-import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
-import org.apache.harmony.luni.lang.reflect.ListOfTypes;
-import org.apache.harmony.luni.lang.reflect.Types;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.ListOfTypes;
+import libcore.reflect.Types;
 
 /**
  * This class represents a method. Information about the method can be accessed,
@@ -80,6 +80,8 @@
 
     private int slot;
 
+    private final int methodDexIndex;
+
     private Class<?> declaringClass;
 
     private String name;
@@ -110,29 +112,19 @@
         }
     }
 
-    /**
-     * Construct a clone of the given instance.
-     *
-     * @param orig non-null; the original instance to clone
-     */
-    /*package*/ Method(Method orig) {
-        this(orig.declaringClass, orig.parameterTypes, orig.exceptionTypes,
-                orig.returnType, orig.name, orig.slot);
-
-        // Copy the accessible flag.
-        if (orig.flag) {
-            this.flag = true;
-        }
-    }
-
-    private Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot)
-    {
+    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() {
diff --git a/luni/src/main/java/java/lang/reflect/Proxy.java b/libdvm/src/main/java/java/lang/reflect/Proxy.java
similarity index 100%
rename from luni/src/main/java/java/lang/reflect/Proxy.java
rename to libdvm/src/main/java/java/lang/reflect/Proxy.java
diff --git a/luni/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java b/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java
similarity index 100%
rename from luni/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java
rename to libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java
diff --git a/luni/src/main/java/sun/misc/Unsafe.java b/libdvm/src/main/java/sun/misc/Unsafe.java
similarity index 100%
rename from luni/src/main/java/sun/misc/Unsafe.java
rename to libdvm/src/main/java/sun/misc/Unsafe.java
diff --git a/luni/src/main/java/java/io/BufferedInputStream.java b/luni/src/main/java/java/io/BufferedInputStream.java
index d45595b..5a810e7 100644
--- a/luni/src/main/java/java/io/BufferedInputStream.java
+++ b/luni/src/main/java/java/io/BufferedInputStream.java
@@ -242,35 +242,14 @@
         return -1;
     }
 
-    /**
-     * Reads at most {@code byteCount} bytes from this stream and stores them in
-     * byte array {@code buffer} starting at offset {@code offset}. Returns the
-     * number of bytes actually read or -1 if no bytes were read and the end of
-     * the stream was encountered. If all the buffered bytes have been used, a
-     * mark has not been set and the requested number of bytes is larger than
-     * the receiver's buffer size, this implementation bypasses the buffer and
-     * simply places the results directly into {@code buffer}.
-     *
-     * @param buffer
-     *            the byte array in which to store the bytes read.
-     * @return the number of bytes actually read or -1 if end of stream.
-     * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code byteCount < 0}, or if
-     *             {@code offset + byteCount} is greater than the size of
-     *             {@code buffer}.
-     * @throws IOException
-     *             if the stream is already closed or another IOException
-     *             occurs.
-     */
-    @Override
-    public synchronized int read(byte[] buffer, int offset, int byteCount) throws IOException {
+    @Override public synchronized int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
         // Use local ref since buf may be invalidated by an unsynchronized
         // close()
         byte[] localBuf = buf;
         if (localBuf == null) {
             throw streamClosed();
         }
-        Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
         if (byteCount == 0) {
             return 0;
         }
@@ -283,12 +262,12 @@
         if (pos < count) {
             /* There are bytes available in the buffer. */
             int copylength = count - pos >= byteCount ? byteCount : count - pos;
-            System.arraycopy(localBuf, pos, buffer, offset, copylength);
+            System.arraycopy(localBuf, pos, buffer, byteOffset, copylength);
             pos += copylength;
             if (copylength == byteCount || localIn.available() == 0) {
                 return copylength;
             }
-            offset += copylength;
+            byteOffset += copylength;
             required = byteCount - copylength;
         } else {
             required = byteCount;
@@ -301,7 +280,7 @@
              * buffer, simply read the bytes directly bypassing the buffer.
              */
             if (markpos == -1 && required >= localBuf.length) {
-                read = localIn.read(buffer, offset, required);
+                read = localIn.read(buffer, byteOffset, required);
                 if (read == -1) {
                     return required == byteCount ? -1 : byteCount - required;
                 }
@@ -318,7 +297,7 @@
                 }
 
                 read = count - pos >= required ? required : count - pos;
-                System.arraycopy(localBuf, pos, buffer, offset, read);
+                System.arraycopy(localBuf, pos, buffer, byteOffset, read);
                 pos += read;
             }
             required -= read;
@@ -328,7 +307,7 @@
             if (localIn.available() == 0) {
                 return byteCount - required;
             }
-            offset += read;
+            byteOffset += read;
         }
     }
 
diff --git a/luni/src/main/java/java/io/BufferedReader.java b/luni/src/main/java/java/io/BufferedReader.java
index 9fba039..c72e798 100644
--- a/luni/src/main/java/java/io/BufferedReader.java
+++ b/luni/src/main/java/java/io/BufferedReader.java
@@ -71,6 +71,21 @@
     private int markLimit = -1;
 
     /**
+     * readLine returns a line as soon as it sees '\n' or '\r'. In the latter
+     * case, there might be a following '\n' that should be treated as part of
+     * the same line ending. Both readLine and all read methods are supposed
+     * to skip the '\n' (and clear this field) but only readLine looks for '\r'
+     * and sets it.
+     */
+    private boolean lastWasCR;
+
+    /**
+     * We also need to keep the 'lastWasCR' state for the mark position, in case
+     * we reset to there.
+     */
+    private boolean markedLastWasCR;
+
+    /**
      * Constructs a new {@code BufferedReader}, providing {@code in} with a buffer
      * of 8192 characters.
      *
@@ -195,7 +210,8 @@
         synchronized (lock) {
             checkNotClosed();
             this.markLimit = markLimit;
-            mark = pos;
+            this.mark = pos;
+            this.markedLastWasCR = lastWasCR;
         }
     }
 
@@ -234,16 +250,24 @@
     public int read() throws IOException {
         synchronized (lock) {
             checkNotClosed();
-            /* Are there buffered characters available? */
-            if (pos < end || fillBuf() != -1) {
-                return buf[pos++];
+            int ch = readChar();
+            if (lastWasCR && ch == '\n') {
+                ch = readChar();
             }
-            return -1;
+            lastWasCR = false;
+            return ch;
         }
     }
 
+    private int readChar() throws IOException {
+        if (pos < end || fillBuf() != -1) {
+            return buf[pos++];
+        }
+        return -1;
+    }
+
     /**
-     * Reads at most {@code length} characters from this reader and stores them
+     * Reads up to {@code length} characters from this reader and stores them
      * at {@code offset} in the character array {@code buffer}. Returns the
      * number of characters actually read or -1 if the end of the source reader
      * has been reached. If all the buffered characters have been used, a mark
@@ -251,20 +275,8 @@
      * this readers buffer size, BufferedReader bypasses the buffer and simply
      * places the results directly into {@code buffer}.
      *
-     * @param buffer
-     *            the character array to store the characters read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the chars read
-     *            from this reader.
-     * @param length
-     *            the maximum number of characters to read, must be
-     *            non-negative.
-     * @return number of characters read or -1 if the end of the source reader
-     *         has been reached.
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code length < 0}, or if
-     *             {@code offset + length} is greater than the size of
-     *             {@code buffer}.
+     *     if {@code offset < 0 || length < 0 || offset + length > buffer.length}.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
      */
@@ -273,12 +285,15 @@
         synchronized (lock) {
             checkNotClosed();
             Arrays.checkOffsetAndCount(buffer.length, offset, length);
+            if (length == 0) {
+                return 0;
+            }
+
+            maybeSwallowLF();
+
             int outstanding = length;
             while (outstanding > 0) {
-
-                /*
-                 * If there are chars in the buffer, grab those first.
-                 */
+                // If there are chars in the buffer, grab those first.
                 int available = end - pos;
                 if (available > 0) {
                     int count = available >= outstanding ? outstanding : available;
@@ -321,7 +336,10 @@
             }
 
             int count = length - outstanding;
-            return (count > 0 || count == length) ? count : -1;
+            if (count > 0) {
+                return count;
+            }
+            return -1;
         }
     }
 
@@ -330,9 +348,16 @@
      * this character is a newline character ("\n"), it is discarded.
      */
     final void chompNewline() throws IOException {
-        if ((pos != end || fillBuf() != -1)
-                && buf[pos] == '\n') {
-            pos++;
+        if ((pos != end || fillBuf() != -1) && buf[pos] == '\n') {
+            ++pos;
+        }
+    }
+
+    // If the last character was CR and the next character is LF, skip it.
+    private void maybeSwallowLF() throws IOException {
+        if (lastWasCR) {
+            chompNewline();
+            lastWasCR = false;
         }
     }
 
@@ -350,77 +375,45 @@
     public String readLine() throws IOException {
         synchronized (lock) {
             checkNotClosed();
-            /* has the underlying stream been exhausted? */
-            if (pos == end && fillBuf() == -1) {
-                return null;
-            }
-            for (int charPos = pos; charPos < end; charPos++) {
-                char ch = buf[charPos];
-                if (ch > '\r') {
-                    continue;
-                }
-                if (ch == '\n') {
-                    String res = new String(buf, pos, charPos - pos);
-                    pos = charPos + 1;
-                    return res;
-                } else if (ch == '\r') {
-                    String res = new String(buf, pos, charPos - pos);
-                    pos = charPos + 1;
-                    if (((pos < end) || (fillBuf() != -1))
-                            && (buf[pos] == '\n')) {
-                        pos++;
-                    }
-                    return res;
+
+            maybeSwallowLF();
+
+            // Do we have a whole line in the buffer?
+            for (int i = pos; i < end; ++i) {
+                char ch = buf[i];
+                if (ch == '\n' || ch == '\r') {
+                    String line = new String(buf, pos, i - pos);
+                    pos = i + 1;
+                    lastWasCR = (ch == '\r');
+                    return line;
                 }
             }
 
-            char eol = '\0';
-            StringBuilder result = new StringBuilder(80);
-            /* Typical Line Length */
-
+            // Accumulate buffers in a StringBuilder until we've read a whole line.
+            StringBuilder result = new StringBuilder(end - pos + 80);
             result.append(buf, pos, end - pos);
             while (true) {
                 pos = end;
-
-                /* Are there buffered characters available? */
-                if (eol == '\n') {
-                    return result.toString();
-                }
-                // attempt to fill buffer
                 if (fillBuf() == -1) {
-                    // characters or null.
-                    return result.length() > 0 || eol != '\0'
-                            ? result.toString()
-                            : null;
+                    // If there's no more input, return what we've read so far, if anything.
+                    return (result.length() > 0) ? result.toString() : null;
                 }
-                for (int charPos = pos; charPos < end; charPos++) {
-                    char c = buf[charPos];
-                    if (eol == '\0') {
-                        if ((c == '\n' || c == '\r')) {
-                            eol = c;
-                        }
-                    } else if (eol == '\r' && c == '\n') {
-                        if (charPos > pos) {
-                            result.append(buf, pos, charPos - pos - 1);
-                        }
-                        pos = charPos + 1;
-                        return result.toString();
-                    } else {
-                        if (charPos > pos) {
-                            result.append(buf, pos, charPos - pos - 1);
-                        }
-                        pos = charPos;
+
+                // Do we have a whole line in the buffer now?
+                for (int i = pos; i < end; ++i) {
+                    char ch = buf[i];
+                    if (ch == '\n' || ch == '\r') {
+                        result.append(buf, pos, i - pos);
+                        pos = i + 1;
+                        lastWasCR = (ch == '\r');
                         return result.toString();
                     }
                 }
-                if (eol == '\0') {
-                    result.append(buf, pos, end - pos);
-                } else {
-                    result.append(buf, pos, end - pos - 1);
-                }
+
+                // Add this whole buffer to the line-in-progress and try again...
+                result.append(buf, pos, end - pos);
             }
         }
-
     }
 
     /**
@@ -459,26 +452,23 @@
             if (mark == -1) {
                 throw new IOException("Invalid mark");
             }
-            pos = mark;
+            this.pos = mark;
+            this.lastWasCR = this.markedLastWasCR;
         }
     }
 
     /**
-     * Skips {@code charCount} chars in this stream. Subsequent calls to
+     * Skips at most {@code charCount} chars in this stream. Subsequent calls to
      * {@code read} will not return these chars unless {@code reset} is
      * used.
      *
      * <p>Skipping characters may invalidate a mark if {@code markLimit}
      * is surpassed.
      *
-     * @param charCount the maximum number of characters to skip.
      * @return the number of characters actually skipped.
      * @throws IllegalArgumentException if {@code charCount < 0}.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @see #mark(int)
-     * @see #markSupported()
-     * @see #reset()
      */
     @Override
     public long skip(long charCount) throws IOException {
@@ -487,9 +477,6 @@
         }
         synchronized (lock) {
             checkNotClosed();
-            if (charCount < 1) {
-                return 0;
-            }
             if (end - pos >= charCount) {
                 pos += charCount;
                 return charCount;
diff --git a/luni/src/main/java/java/io/ByteArrayInputStream.java b/luni/src/main/java/java/io/ByteArrayInputStream.java
index 0a8c453..7a6cc50 100644
--- a/luni/src/main/java/java/io/ByteArrayInputStream.java
+++ b/luni/src/main/java/java/io/ByteArrayInputStream.java
@@ -141,41 +141,19 @@
         return pos < count ? buf[pos++] & 0xFF : -1;
     }
 
-    /**
-     * Reads at most {@code len} bytes from this stream and stores
-     * them in byte array {@code b} starting at {@code offset}. This
-     * implementation reads bytes from the source byte array.
-     *
-     * @param buffer
-     *            the byte array in which to store the bytes read.
-     * @param offset
-     *            the initial position in {@code b} to store the bytes read from
-     *            this stream.
-     * @param length
-     *            the maximum number of bytes to store in {@code b}.
-     * @return the number of bytes actually read or -1 if no bytes were read and
-     *         the end of the stream was encountered.
-     * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code length < 0}, or if
-     *             {@code offset + length} is greater than the size of
-     *             {@code b}.
-     * @throws NullPointerException
-     *             if {@code b} is {@code null}.
-     */
-    @Override
-    public synchronized int read(byte[] buffer, int offset, int length) {
-        Arrays.checkOffsetAndCount(buffer.length, offset, length);
+    @Override public synchronized int read(byte[] buffer, int byteOffset, int byteCount) {
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
 
         // Are there any bytes available?
         if (this.pos >= this.count) {
             return -1;
         }
-        if (length == 0) {
+        if (byteCount == 0) {
             return 0;
         }
 
-        int copylen = this.count - pos < length ? this.count - pos : length;
-        System.arraycopy(this.buf, pos, buffer, offset, copylen);
+        int copylen = this.count - pos < byteCount ? this.count - pos : byteCount;
+        System.arraycopy(this.buf, pos, buffer, byteOffset, copylen);
         pos += copylen;
         return copylen;
     }
diff --git a/luni/src/main/java/java/io/ByteArrayOutputStream.java b/luni/src/main/java/java/io/ByteArrayOutputStream.java
index ff9c7df..45f217b 100644
--- a/luni/src/main/java/java/io/ByteArrayOutputStream.java
+++ b/luni/src/main/java/java/io/ByteArrayOutputStream.java
@@ -149,7 +149,7 @@
      *            the high byte of each resulting Unicode character.
      * @return this stream's current contents as a string with the high byte set
      *         to {@code hibyte}.
-     * @deprecated Use {@link #toString()}.
+     * @deprecated Use {@link #toString()} instead.
      */
     @Deprecated
     public String toString(int hibyte) {
diff --git a/luni/src/main/java/java/io/CharArrayReader.java b/luni/src/main/java/java/io/CharArrayReader.java
index 366efcf..c5baa32 100644
--- a/luni/src/main/java/java/io/CharArrayReader.java
+++ b/luni/src/main/java/java/io/CharArrayReader.java
@@ -184,34 +184,23 @@
     }
 
     /**
-     * Reads at most {@code count} characters from this CharArrayReader and
-     * stores them at {@code offset} in the character array {@code buf}.
+     * Reads up to {@code count} characters from this CharArrayReader and
+     * stores them at {@code offset} in the character array {@code buffer}.
      * Returns the number of characters actually read or -1 if the end of reader
      * was encountered.
      *
-     * @param buffer
-     *            the character array to store the characters read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the characters
-     *            read from this reader.
-     * @param len
-     *            the maximum number of characters to read.
-     * @return number of characters read or -1 if the end of the reader has been
-     *         reached.
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code len < 0}, or if
-     *             {@code offset + len} is bigger than the size of
-     *             {@code buffer}.
+     * if {@code offset < 0 || count < 0 || offset + count > buffer.length}.
      * @throws IOException
      *             if this reader is closed.
      */
     @Override
-    public int read(char[] buffer, int offset, int len) throws IOException {
-        Arrays.checkOffsetAndCount(buffer.length, offset, len);
+    public int read(char[] buffer, int offset, int count) throws IOException {
+        Arrays.checkOffsetAndCount(buffer.length, offset, count);
         synchronized (lock) {
             checkNotClosed();
             if (pos < this.count) {
-                int bytesRead = pos + len > this.count ? this.count - pos : len;
+                int bytesRead = pos + count > this.count ? this.count - pos : count;
                 System.arraycopy(this.buf, pos, buffer, offset, bytesRead);
                 pos += bytesRead;
                 return bytesRead;
diff --git a/luni/src/main/java/java/io/DataInputStream.java b/luni/src/main/java/java/io/DataInputStream.java
index 7826852..3b1a6d0 100644
--- a/luni/src/main/java/java/io/DataInputStream.java
+++ b/luni/src/main/java/java/io/DataInputStream.java
@@ -59,29 +59,8 @@
         return super.read(buffer);
     }
 
-    /**
-     * Reads at most {@code length} bytes from this stream and stores them in
-     * the byte array {@code buffer} starting at {@code offset}. Returns the
-     * number of bytes that have been read or -1 if no bytes have been read and
-     * the end of the stream has been reached.
-     *
-     * @param buffer
-     *            the byte array in which to store the bytes read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the bytes
-     *            read from this stream.
-     * @param length
-     *            the maximum number of bytes to store in {@code buffer}.
-     * @return the number of bytes that have been read or -1 if the end of the
-     *         stream has been reached.
-     * @throws IOException
-     *             if a problem occurs while reading from this stream.
-     * @see DataOutput#write(byte[])
-     * @see DataOutput#write(byte[], int, int)
-     */
-    @Override
-    public final int read(byte[] buffer, int offset, int length) throws IOException {
-        return in.read(buffer, offset, length);
+    @Override public final int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+        return in.read(buffer, byteOffset, byteCount);
     }
 
     public final boolean readBoolean() throws IOException {
@@ -125,6 +104,10 @@
         return Memory.peekInt(scratch, 0, ByteOrder.BIG_ENDIAN);
     }
 
+    /**
+     * @deprecated This method cannot be trusted to convert bytes to characters correctly.
+     * Wrap this stream with a {@link BufferedReader} instead.
+     */
     @Deprecated
     public final String readLine() throws IOException {
         StringBuilder line = new StringBuilder(80); // Typical line length
diff --git a/luni/src/main/java/java/io/File.java b/luni/src/main/java/java/io/File.java
index ec87fed..a8b4810 100644
--- a/luni/src/main/java/java/io/File.java
+++ b/luni/src/main/java/java/io/File.java
@@ -27,7 +27,7 @@
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
 import libcore.io.StructStat;
-import libcore.io.StructStatFs;
+import libcore.io.StructStatVfs;
 import org.apache.harmony.luni.util.DeleteOnExit;
 import static libcore.io.OsConstants.*;
 
@@ -487,8 +487,6 @@
 
     /**
      * Returns the path of this file.
-     *
-     * @return this file's path.
      */
     public String getPath() {
         return path;
@@ -1084,8 +1082,8 @@
      * @return a URL for this file.
      * @throws java.net.MalformedURLException
      *             if the path cannot be transformed into a URL.
-     * @deprecated use {@link #toURI} and {@link java.net.URI#toURL} to get
-     * correct escaping of illegal characters.
+     * @deprecated Use {@link #toURI} and {@link java.net.URI#toURL} to
+     * correctly escape illegal characters.
      */
     @Deprecated
     public URL toURL() throws java.net.MalformedURLException {
@@ -1132,7 +1130,7 @@
      */
     public long getTotalSpace() {
         try {
-            StructStatFs sb = Libcore.os.statfs(path);
+            StructStatVfs sb = Libcore.os.statvfs(path);
             return sb.f_blocks * sb.f_bsize; // total block count * block size in bytes.
         } catch (ErrnoException errnoException) {
             return 0;
@@ -1154,7 +1152,7 @@
      */
     public long getUsableSpace() {
         try {
-            StructStatFs sb = Libcore.os.statfs(path);
+            StructStatVfs sb = Libcore.os.statvfs(path);
             return sb.f_bavail * sb.f_bsize; // non-root free block count * block size in bytes.
         } catch (ErrnoException errnoException) {
             return 0;
@@ -1172,7 +1170,7 @@
      */
     public long getFreeSpace() {
         try {
-            StructStatFs sb = Libcore.os.statfs(path);
+            StructStatVfs sb = Libcore.os.statvfs(path);
             return sb.f_bfree * sb.f_bsize; // free block count * block size in bytes.
         } catch (ErrnoException errnoException) {
             return 0;
diff --git a/luni/src/main/java/java/io/FileInputStream.java b/luni/src/main/java/java/io/FileInputStream.java
index 537607a..b2e620f 100644
--- a/luni/src/main/java/java/io/FileInputStream.java
+++ b/luni/src/main/java/java/io/FileInputStream.java
@@ -53,7 +53,7 @@
  * @see BufferedInputStream
  * @see FileOutputStream
  */
-public class FileInputStream extends InputStream implements Closeable {
+public class FileInputStream extends InputStream {
 
     private FileDescriptor fd;
     private final boolean shouldClose;
diff --git a/luni/src/main/java/java/io/FileOutputStream.java b/luni/src/main/java/java/io/FileOutputStream.java
index 6787112..e04ab5f 100644
--- a/luni/src/main/java/java/io/FileOutputStream.java
+++ b/luni/src/main/java/java/io/FileOutputStream.java
@@ -50,7 +50,7 @@
  * @see BufferedOutputStream
  * @see FileInputStream
  */
-public class FileOutputStream extends OutputStream implements Closeable {
+public class FileOutputStream extends OutputStream {
 
     private FileDescriptor fd;
     private final boolean shouldClose;
diff --git a/luni/src/main/java/java/io/FilterInputStream.java b/luni/src/main/java/java/io/FilterInputStream.java
index 2bf13e2..4092cd4 100644
--- a/luni/src/main/java/java/io/FilterInputStream.java
+++ b/luni/src/main/java/java/io/FilterInputStream.java
@@ -114,28 +114,8 @@
         return in.read();
     }
 
-    /**
-     * Reads at most {@code count} bytes from this stream and stores them in the
-     * byte array {@code buffer} starting at {@code offset}. Returns the number
-     * of bytes actually read or -1 if no bytes have been read and the end of
-     * this stream has been reached. This implementation reads bytes from the
-     * filtered stream.
-     *
-     * @param buffer
-     *            the byte array in which to store the bytes read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the bytes
-     *            read from this stream.
-     * @param count
-     *            the maximum number of bytes to store in {@code buffer}.
-     * @return the number of bytes actually read or -1 if the end of the
-     *         filtered stream has been reached while reading.
-     * @throws IOException
-     *             if this stream is closed or another I/O error occurs.
-     */
-    @Override
-    public int read(byte[] buffer, int offset, int count) throws IOException {
-        return in.read(buffer, offset, count);
+    @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+        return in.read(buffer, byteOffset, byteCount);
     }
 
     /**
diff --git a/luni/src/main/java/java/io/FilterReader.java b/luni/src/main/java/java/io/FilterReader.java
index 43beb8c..e93fe9c 100644
--- a/luni/src/main/java/java/io/FilterReader.java
+++ b/luni/src/main/java/java/io/FilterReader.java
@@ -116,20 +116,11 @@
     }
 
     /**
-     * Reads at most {@code count} characters from the filtered reader and stores them
+     * Reads up to {@code count} characters from the filtered reader and stores them
      * in the byte array {@code buffer} starting at {@code offset}. Returns the
      * number of characters actually read or -1 if no characters were read and
      * the end of the filtered reader was encountered.
      *
-     * @param buffer
-     *            the char array in which to store the characters read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the characters
-     *            read from this reader.
-     * @param count
-     *            the maximum number of characters to store in {@code buffer}.
-     * @return the number of characters actually read or -1 if the end of the
-     *         filtered reader has been reached while reading.
      * @throws IOException
      *             if an error occurs while reading from this reader.
      */
diff --git a/luni/src/main/java/java/io/HistoricalCharsetNames.java b/luni/src/main/java/java/io/HistoricalCharsetNames.java
deleted file mode 100644
index b0d5498..0000000
--- a/luni/src/main/java/java/io/HistoricalCharsetNames.java
+++ /dev/null
@@ -1,175 +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.io;
-
-import java.nio.charset.Charset;
-import java.util.HashMap;
-
-/**
- * This could have been in Charset or Charsets, but all code uses those classes whereas no code
- * should need to use this, so let's not make good code pay to initialize this map.
- */
-class HistoricalCharsetNames {
-    private static final HashMap<String, String> historicalNames = new HashMap<String, String>();
-    static {
-        historicalNames.put("Big5-HKSCS", "Big5_HKSCS");
-        historicalNames.put("EUC-JP", "EUC_JP");
-        historicalNames.put("EUC-KR", "EUC_KR");
-        historicalNames.put("GB2312", "EUC_CN");
-        historicalNames.put("IBM-Thai", "Cp838");
-        historicalNames.put("IBM00858", "Cp858");
-        historicalNames.put("IBM01140", "Cp1140");
-        historicalNames.put("IBM01141", "Cp1141");
-        historicalNames.put("IBM01142", "Cp1142");
-        historicalNames.put("IBM01143", "Cp1143");
-        historicalNames.put("IBM01144", "Cp1144");
-        historicalNames.put("IBM01145", "Cp1145");
-        historicalNames.put("IBM01146", "Cp1146");
-        historicalNames.put("IBM01147", "Cp1147");
-        historicalNames.put("IBM01148", "Cp1148");
-        historicalNames.put("IBM01149", "Cp1149");
-        historicalNames.put("IBM037", "Cp037");
-        historicalNames.put("IBM1026", "Cp1026");
-        historicalNames.put("IBM1047", "Cp1047");
-        historicalNames.put("IBM273", "Cp273");
-        historicalNames.put("IBM277", "Cp277");
-        historicalNames.put("IBM278", "Cp278");
-        historicalNames.put("IBM280", "Cp280");
-        historicalNames.put("IBM284", "Cp284");
-        historicalNames.put("IBM285", "Cp285");
-        historicalNames.put("IBM297", "Cp297");
-        historicalNames.put("IBM420", "Cp420");
-        historicalNames.put("IBM424", "Cp424");
-        historicalNames.put("IBM437", "Cp437");
-        historicalNames.put("IBM500", "Cp500");
-        historicalNames.put("IBM775", "Cp775");
-        historicalNames.put("IBM850", "Cp850");
-        historicalNames.put("IBM852", "Cp852");
-        historicalNames.put("IBM855", "Cp855");
-        historicalNames.put("IBM857", "Cp857");
-        historicalNames.put("IBM860", "Cp860");
-        historicalNames.put("IBM861", "Cp861");
-        historicalNames.put("IBM862", "Cp862");
-        historicalNames.put("IBM863", "Cp863");
-        historicalNames.put("IBM864", "Cp864");
-        historicalNames.put("IBM865", "Cp865");
-        historicalNames.put("IBM866", "Cp866");
-        historicalNames.put("IBM868", "Cp868");
-        historicalNames.put("IBM869", "Cp869");
-        historicalNames.put("IBM870", "Cp870");
-        historicalNames.put("IBM871", "Cp871");
-        historicalNames.put("IBM918", "Cp918");
-        historicalNames.put("ISO-2022-CN", "ISO2022CN");
-        historicalNames.put("ISO-2022-JP", "ISO2022JP");
-        historicalNames.put("ISO-2022-KR", "ISO2022KR");
-        historicalNames.put("ISO-8859-1", "ISO8859_1");
-        historicalNames.put("ISO-8859-13", "ISO8859_13");
-        historicalNames.put("ISO-8859-15", "ISO8859_15");
-        historicalNames.put("ISO-8859-2", "ISO8859_2");
-        historicalNames.put("ISO-8859-3", "ISO8859_3");
-        historicalNames.put("ISO-8859-4", "ISO8859_4");
-        historicalNames.put("ISO-8859-5", "ISO8859_5");
-        historicalNames.put("ISO-8859-6", "ISO8859_6");
-        historicalNames.put("ISO-8859-7", "ISO8859_7");
-        historicalNames.put("ISO-8859-8", "ISO8859_8");
-        historicalNames.put("ISO-8859-9", "ISO8859_9");
-        historicalNames.put("KOI8-R", "KOI8_R");
-        historicalNames.put("Shift_JIS", "SJIS");
-        historicalNames.put("TIS-620", "TIS620");
-        historicalNames.put("US-ASCII", "ASCII");
-        historicalNames.put("UTF-16BE", "UnicodeBigUnmarked");
-        historicalNames.put("UTF-16LE", "UnicodeLittleUnmarked");
-        historicalNames.put("UTF-8", "UTF8");
-        historicalNames.put("windows-1250", "Cp1250");
-        historicalNames.put("windows-1251", "Cp1251");
-        historicalNames.put("windows-1252", "Cp1252");
-        historicalNames.put("windows-1253", "Cp1253");
-        historicalNames.put("windows-1254", "Cp1254");
-        historicalNames.put("windows-1255", "Cp1255");
-        historicalNames.put("windows-1256", "Cp1256");
-        historicalNames.put("windows-1257", "Cp1257");
-        historicalNames.put("windows-1258", "Cp1258");
-        historicalNames.put("windows-31j", "MS932");
-        historicalNames.put("x-Big5-Solaris", "Big5_Solaris");
-        historicalNames.put("x-euc-jp-linux", "EUC_JP_LINUX");
-        historicalNames.put("x-EUC-TW", "EUC_TW");
-        historicalNames.put("x-eucJP-Open", "EUC_JP_Solaris");
-        historicalNames.put("x-IBM1006", "Cp1006");
-        historicalNames.put("x-IBM1025", "Cp1025");
-        historicalNames.put("x-IBM1046", "Cp1046");
-        historicalNames.put("x-IBM1097", "Cp1097");
-        historicalNames.put("x-IBM1098", "Cp1098");
-        historicalNames.put("x-IBM1112", "Cp1112");
-        historicalNames.put("x-IBM1122", "Cp1122");
-        historicalNames.put("x-IBM1123", "Cp1123");
-        historicalNames.put("x-IBM1124", "Cp1124");
-        historicalNames.put("x-IBM1381", "Cp1381");
-        historicalNames.put("x-IBM1383", "Cp1383");
-        historicalNames.put("x-IBM33722", "Cp33722");
-        historicalNames.put("x-IBM737", "Cp737");
-        historicalNames.put("x-IBM856", "Cp856");
-        historicalNames.put("x-IBM874", "Cp874");
-        historicalNames.put("x-IBM875", "Cp875");
-        historicalNames.put("x-IBM921", "Cp921");
-        historicalNames.put("x-IBM922", "Cp922");
-        historicalNames.put("x-IBM930", "Cp930");
-        historicalNames.put("x-IBM933", "Cp933");
-        historicalNames.put("x-IBM935", "Cp935");
-        historicalNames.put("x-IBM937", "Cp937");
-        historicalNames.put("x-IBM939", "Cp939");
-        historicalNames.put("x-IBM942", "Cp942");
-        historicalNames.put("x-IBM942C", "Cp942C");
-        historicalNames.put("x-IBM943", "Cp943");
-        historicalNames.put("x-IBM943C", "Cp943C");
-        historicalNames.put("x-IBM948", "Cp948");
-        historicalNames.put("x-IBM949", "Cp949");
-        historicalNames.put("x-IBM949C", "Cp949C");
-        historicalNames.put("x-IBM950", "Cp950");
-        historicalNames.put("x-IBM964", "Cp964");
-        historicalNames.put("x-IBM970", "Cp970");
-        historicalNames.put("x-ISCII91", "ISCII91");
-        historicalNames.put("x-ISO-2022-CN-CNS", "ISO2022CN");
-        historicalNames.put("x-ISO-2022-CN-GB", "ISO2022CN");
-        historicalNames.put("x-JISAutoDetect", "JISAutoDetect");
-        historicalNames.put("x-MacArabic", "MacArabic");
-        historicalNames.put("x-MacCentralEurope", "MacCentralEurope");
-        historicalNames.put("x-MacCroatian", "MacCroatian");
-        historicalNames.put("x-MacCyrillic", "MacCyrillic");
-        historicalNames.put("x-MacDingbat", "MacDingbat");
-        historicalNames.put("x-MacGreek", "MacGreek");
-        historicalNames.put("x-MacHebrew", "MacHebrew");
-        historicalNames.put("x-MacIceland", "MacIceland");
-        historicalNames.put("x-MacRoman", "MacRoman");
-        historicalNames.put("x-MacRomania", "MacRomania");
-        historicalNames.put("x-MacSymbol", "MacSymbol");
-        historicalNames.put("x-MacThai", "MacThai");
-        historicalNames.put("x-MacTurkish", "MacTurkish");
-        historicalNames.put("x-MacUkraine", "MacUkraine");
-        historicalNames.put("x-MS950-HKSCS", "MS950_HKSCS");
-        historicalNames.put("x-mswin-936", "MS936");
-        historicalNames.put("x-PCK", "PCK");
-        historicalNames.put("x-windows-874", "MS874");
-        historicalNames.put("x-windows-949", "MS949");
-        historicalNames.put("x-windows-950", "MS950");
-    }
-
-    public static String get(Charset charset) {
-        String modernName = charset.name();
-        String result = historicalNames.get(modernName);
-        return (result != null) ? result : modernName;
-    }
-}
diff --git a/luni/src/main/java/java/io/InputStream.java b/luni/src/main/java/java/io/InputStream.java
index 561e057..973382e 100644
--- a/luni/src/main/java/java/io/InputStream.java
+++ b/luni/src/main/java/java/io/InputStream.java
@@ -150,7 +150,6 @@
      * reached. Blocks until one byte has been read, the end of the source
      * stream is detected or an exception is thrown.
      *
-     * @return the byte read or -1 if the end of stream has been reached.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
      */
@@ -164,28 +163,19 @@
     }
 
     /**
-     * Reads at most {@code length} bytes from this stream and stores them in
-     * the byte array {@code b} starting at {@code offset}.
+     * Reads up to {@code byteCount} bytes from this stream and stores them in
+     * the byte array {@code buffer} starting at {@code byteOffset}.
+     * Returns the number of bytes actually read or -1 if the end of the stream
+     * has been reached.
      *
-     * @param buffer
-     *            the byte array in which to store the bytes read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the bytes read
-     *            from this stream.
-     * @param length
-     *            the maximum number of bytes to store in {@code b}.
-     * @return the number of bytes actually read or -1 if the end of the stream
-     *         has been reached.
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code length < 0}, or if
-     *             {@code offset + length} is greater than the length of
-     *             {@code b}.
+     *   if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > buffer.length}.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
      */
-    public int read(byte[] buffer, int offset, int length) throws IOException {
-        Arrays.checkOffsetAndCount(buffer.length, offset, length);
-        for (int i = 0; i < length; i++) {
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
+        for (int i = 0; i < byteCount; ++i) {
             int c;
             try {
                 if ((c = read()) == -1) {
@@ -197,9 +187,9 @@
                 }
                 throw e;
             }
-            buffer[offset + i] = (byte) c;
+            buffer[byteOffset + i] = (byte) c;
         }
-        return length;
+        return byteCount;
     }
 
     /**
diff --git a/luni/src/main/java/java/io/InputStreamReader.java b/luni/src/main/java/java/io/InputStreamReader.java
index d3650dc..01e7f29 100644
--- a/luni/src/main/java/java/io/InputStreamReader.java
+++ b/luni/src/main/java/java/io/InputStreamReader.java
@@ -149,7 +149,7 @@
     }
 
     /**
-     * Returns the historical name of the encoding used by this writer to convert characters to
+     * Returns the canonical name of the encoding used by this writer to convert characters to
      * bytes, or null if this writer has been closed. Most callers should probably keep
      * track of the String or Charset they passed in; this method may not return the same
      * name.
@@ -158,7 +158,7 @@
         if (!isOpen()) {
             return null;
         }
-        return HistoricalCharsetNames.get(decoder.charset());
+        return decoder.charset().name();
     }
 
     /**
@@ -185,42 +185,31 @@
     }
 
     /**
-     * Reads at most {@code length} characters from this reader and stores them
-     * at position {@code offset} in the character array {@code buf}. Returns
+     * Reads up to {@code count} characters from this reader and stores them
+     * at position {@code offset} in the character array {@code buffer}. Returns
      * the number of characters actually read or -1 if the end of the reader has
      * been reached. The bytes are either obtained from converting bytes in this
      * reader's buffer or by first filling the buffer from the source
      * InputStream and then reading from the buffer.
      *
-     * @param buffer
-     *            the array to store the characters read.
-     * @param offset
-     *            the initial position in {@code buf} to store the characters
-     *            read from this reader.
-     * @param length
-     *            the maximum number of characters to read.
-     * @return the number of characters read or -1 if the end of the reader has
-     *         been reached.
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code length < 0}, or if
-     *             {@code offset + length} is greater than the length of
-     *             {@code buf}.
+     *     if {@code offset < 0 || count < 0 || offset + count > buffer.length}.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
      */
     @Override
-    public int read(char[] buffer, int offset, int length) throws IOException {
+    public int read(char[] buffer, int offset, int count) throws IOException {
         synchronized (lock) {
             if (!isOpen()) {
                 throw new IOException("InputStreamReader is closed");
             }
 
-            Arrays.checkOffsetAndCount(buffer.length, offset, length);
-            if (length == 0) {
+            Arrays.checkOffsetAndCount(buffer.length, offset, count);
+            if (count == 0) {
                 return 0;
             }
 
-            CharBuffer out = CharBuffer.wrap(buffer, offset, length);
+            CharBuffer out = CharBuffer.wrap(buffer, offset, count);
             CoderResult result = CoderResult.UNDERFLOW;
 
             // bytes.remaining() indicates number of bytes in buffer
diff --git a/luni/src/main/java/java/io/LineNumberInputStream.java b/luni/src/main/java/java/io/LineNumberInputStream.java
index 4d1cf14..de6584e 100644
--- a/luni/src/main/java/java/io/LineNumberInputStream.java
+++ b/luni/src/main/java/java/io/LineNumberInputStream.java
@@ -27,7 +27,7 @@
  * When using {@code read}, line terminator sequences are always translated into
  * {@code '\n'}.
  *
- * @deprecated Use {@link LineNumberReader}
+ * @deprecated Use {@link LineNumberReader} instead.
  */
 @Deprecated
 public class LineNumberInputStream extends FilterInputStream {
@@ -138,38 +138,27 @@
     }
 
     /**
-     * Reads at most {@code length} bytes from the filtered stream and stores
-     * them in the byte array {@code buffer} starting at {@code offset}.
+     * Reads up to {@code byteCount} bytes from the filtered stream and stores
+     * them in the byte array {@code buffer} starting at {@code byteOffset}.
      * Returns the number of bytes actually read or -1 if no bytes have been
      * read and the end of this stream has been reached.
-     * <p>
-     * The line number count is incremented if a line terminator is encountered.
+     *
+     * <p>The line number count is incremented if a line terminator is encountered.
      * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
      * {@code "\r\n"}. Line terminator sequences are always translated into
      * {@code '\n'}.
      *
-     * @param buffer
-     *            the array in which to store the bytes read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the bytes read
-     *            from this stream.
-     * @param length
-     *            the maximum number of bytes to store in {@code buffer}.
-     * @return the number of bytes actually read or -1 if the end of the
-     *         filtered stream has been reached while reading.
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code length < 0}, or if
-     *             {@code offset + length} is greater than the length of
-     *             {@code buffer}.
+     *     if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > buffer.length}.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
      * @throws NullPointerException
-     *             if {@code buffer} is {@code null}.
+     *             if {@code buffer == null}.
      */
     @Override
-    public int read(byte[] buffer, int offset, int length) throws IOException {
-        Arrays.checkOffsetAndCount(buffer.length, offset, length);
-        for (int i = 0; i < length; i++) {
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
+        for (int i = 0; i < byteCount; ++i) {
             int currentChar;
             try {
                 currentChar = read();
@@ -182,9 +171,9 @@
             if (currentChar == -1) {
                 return i == 0 ? -1 : i;
             }
-            buffer[offset + i] = (byte) currentChar;
+            buffer[byteOffset + i] = (byte) currentChar;
         }
-        return length;
+        return byteCount;
     }
 
     /**
diff --git a/luni/src/main/java/java/io/LineNumberReader.java b/luni/src/main/java/java/io/LineNumberReader.java
index 03d02a2..5295e77 100644
--- a/luni/src/main/java/java/io/LineNumberReader.java
+++ b/luni/src/main/java/java/io/LineNumberReader.java
@@ -132,24 +132,15 @@
     }
 
     /**
-     * Reads at most {@code count} characters from the source reader and stores
+     * Reads up to {@code count} characters from the source reader and stores
      * them in the character array {@code buffer} starting at {@code offset}.
      * Returns the number of characters actually read or -1 if no characters
      * have been read and the end of this reader has been reached.
-     * <p>
-     * The line number count is incremented if a line terminator is encountered.
+     *
+     * <p>The line number count is incremented if a line terminator is encountered.
      * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
      * {@code "\r\n"}.
      *
-     * @param buffer
-     *            the array in which to store the characters read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the characters
-     *            read from this reader.
-     * @param count
-     *            the maximum number of characters to store in {@code buffer}.
-     * @return the number of characters actually read or -1 if the end of the
-     *         source reader has been reached while reading.
      * @throws IOException
      *             if this reader is closed or another IOException occurs.
      */
diff --git a/luni/src/main/java/java/io/ObjectInput.java b/luni/src/main/java/java/io/ObjectInput.java
index e892071..0c137c0 100644
--- a/luni/src/main/java/java/io/ObjectInput.java
+++ b/luni/src/main/java/java/io/ObjectInput.java
@@ -56,35 +56,24 @@
 
     /**
      * Reads bytes from this stream into the byte array {@code buffer}. Blocks
-     * while waiting for input.
+     * while waiting for input. Returns the number of bytes read,
+     * or -1 if the end of this stream has been reached.
      *
-     * @param buffer
-     *            the array in which to store the bytes read.
-     * @return the number of bytes read or -1 if the end of this stream has been
-     *         reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
      */
     public int read(byte[] buffer) throws IOException;
 
     /**
-     * Reads at most {@code count} bytes from this stream and stores them in
-     * byte array {@code buffer} starting at offset {@code count}. Blocks while
-     * waiting for input.
+     * Reads up to {@code byteCount} bytes from this stream and stores them in
+     * byte array {@code buffer} starting at offset {@code byteOffset}. Blocks while
+     * waiting for input. Returns the number of bytes read or -1 if the end of this stream has been
+     * reached.
      *
-     * @param buffer
-     *            the array in which to store the bytes read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the bytes read
-     *            from this stream.
-     * @param count
-     *            the maximum number of bytes to store in {@code buffer}.
-     * @return the number of bytes read or -1 if the end of this stream has been
-     *         reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
      */
-    public int read(byte[] buffer, int offset, int count) throws IOException;
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException;
 
     /**
      * Reads the next object from this stream.
diff --git a/luni/src/main/java/java/io/ObjectInputStream.java b/luni/src/main/java/java/io/ObjectInputStream.java
index 9be8206..17a6974 100644
--- a/luni/src/main/java/java/io/ObjectInputStream.java
+++ b/luni/src/main/java/java/io/ObjectInputStream.java
@@ -530,38 +530,13 @@
         return primitiveData.read();
     }
 
-    /**
-     * Reads at most {@code length} bytes from the source stream and stores them
-     * in byte array {@code buffer} starting at offset {@code count}. Blocks
-     * until {@code count} bytes have been read, the end of the source stream is
-     * detected or an exception is thrown.
-     *
-     * @param buffer
-     *            the array in which to store the bytes read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the bytes
-     *            read from the source stream.
-     * @param length
-     *            the maximum number of bytes to store in {@code buffer}.
-     * @return the number of bytes read or -1 if the end of the source input
-     *         stream has been reached.
-     * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code length < 0}, or if
-     *             {@code offset + length} is greater than the length of
-     *             {@code buffer}.
-     * @throws IOException
-     *             if an error occurs while reading from this stream.
-     * @throws NullPointerException
-     *             if {@code buffer} is {@code null}.
-     */
-    @Override
-    public int read(byte[] buffer, int offset, int length) throws IOException {
-        Arrays.checkOffsetAndCount(buffer.length, offset, length);
-        if (length == 0) {
+    @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
+        if (byteCount == 0) {
             return 0;
         }
         checkReadPrimitiveTypes();
-        return primitiveData.read(buffer, offset, length);
+        return primitiveData.read(buffer, byteOffset, byteCount);
     }
 
     /**
@@ -1402,7 +1377,7 @@
      * @return the string read from the source stream.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @deprecated Use {@link BufferedReader}
+     * @deprecated Use {@link BufferedReader} instead.
      */
     @Deprecated
     public String readLine() throws IOException {
@@ -2004,7 +1979,7 @@
             // original/outside caller
             if (++nestedLevels == 1) {
                 // Remember the caller's class loader
-                callerClassLoader = getClosestUserClassLoader();
+                callerClassLoader = VMStack.getClosestUserClassLoader(bootstrapLoader, systemLoader);
             }
 
             result = readNonPrimitiveContent(unshared);
@@ -2045,23 +2020,6 @@
     private static final ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
 
     /**
-     * Searches up the call stack to find the closest user-defined class loader.
-     *
-     * @return a user-defined class loader or null if one isn't found
-     */
-    private static ClassLoader getClosestUserClassLoader() {
-        Class<?>[] stackClasses = VMStack.getClasses(-1);
-        for (Class<?> stackClass : stackClasses) {
-            ClassLoader loader = stackClass.getClassLoader();
-            if (loader != null && loader != bootstrapLoader
-                    && loader != systemLoader) {
-                return loader;
-            }
-        }
-        return null;
-    }
-
-    /**
      * Method to be overridden by subclasses to read the next object from the
      * source stream.
      *
diff --git a/luni/src/main/java/java/io/OutputStreamWriter.java b/luni/src/main/java/java/io/OutputStreamWriter.java
index 5dffdfe..d69c87a 100644
--- a/luni/src/main/java/java/io/OutputStreamWriter.java
+++ b/luni/src/main/java/java/io/OutputStreamWriter.java
@@ -225,7 +225,7 @@
     }
 
     /**
-     * Returns the historical name of the encoding used by this writer to convert characters to
+     * Returns the canonical name of the encoding used by this writer to convert characters to
      * bytes, or null if this writer has been closed. Most callers should probably keep
      * track of the String or Charset they passed in; this method may not return the same
      * name.
@@ -234,7 +234,7 @@
         if (encoder == null) {
             return null;
         }
-        return HistoricalCharsetNames.get(encoder.charset());
+        return encoder.charset().name();
     }
 
     /**
diff --git a/luni/src/main/java/java/io/PipedInputStream.java b/luni/src/main/java/java/io/PipedInputStream.java
index 739fb98..2c27695 100644
--- a/luni/src/main/java/java/io/PipedInputStream.java
+++ b/luni/src/main/java/java/io/PipedInputStream.java
@@ -256,20 +256,20 @@
     }
 
     /**
-     * Reads at most {@code byteCount} bytes from this stream and stores them in the
-     * byte array {@code bytes} starting at {@code offset}. Blocks until at
+     * Reads up to {@code byteCount} bytes from this stream and stores them in the
+     * byte array {@code bytes} starting at {@code byteOffset}. Blocks until at
      * least one byte has been read, the end of the stream is detected or an
      * exception is thrown.
-     * <p>
-     * Separate threads should be used to read from a {@code PipedInputStream}
+     *
+     * <p>Separate threads should be used to read from a {@code PipedInputStream}
      * and to write to the connected {@link PipedOutputStream}. If the same
      * thread is used, a deadlock may occur.
      *
-     * @return the number of bytes actually read or -1 if the end of the stream
-     *         has been reached.
+     * <p>Returns the number of bytes actually read or -1 if the end of the stream
+     * has been reached.
+     *
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code byteCount < 0}, or if {@code
-     *             offset + byteCount} is greater than the size of {@code bytes}.
+     *     if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > bytes.length}.
      * @throws InterruptedIOException
      *             if the thread reading from this stream is interrupted.
      * @throws IOException
@@ -279,9 +279,8 @@
      * @throws NullPointerException
      *             if {@code bytes} is {@code null}.
      */
-    @Override
-    public synchronized int read(byte[] bytes, int offset, int byteCount) throws IOException {
-        Arrays.checkOffsetAndCount(bytes.length, offset, byteCount);
+    @Override public synchronized int read(byte[] bytes, int byteOffset, int byteCount) throws IOException {
+        Arrays.checkOffsetAndCount(bytes.length, byteOffset, byteCount);
         if (byteCount == 0) {
             return 0;
         }
@@ -324,7 +323,7 @@
         if (out >= in) {
             int leftInBuffer = buffer.length - out;
             int length = leftInBuffer < byteCount ? leftInBuffer : byteCount;
-            System.arraycopy(buffer, out, bytes, offset, length);
+            System.arraycopy(buffer, out, bytes, byteOffset, length);
             out += length;
             if (out == buffer.length) {
                 out = 0;
@@ -342,7 +341,7 @@
             int leftInBuffer = in - out;
             int leftToCopy = byteCount - totalCopied;
             int length = leftToCopy < leftInBuffer ? leftToCopy : leftInBuffer;
-            System.arraycopy(buffer, out, bytes, offset + totalCopied, length);
+            System.arraycopy(buffer, out, bytes, byteOffset + totalCopied, length);
             out += length;
             if (out == in) {
                 // empty buffer
diff --git a/luni/src/main/java/java/io/PipedReader.java b/luni/src/main/java/java/io/PipedReader.java
index 8450a34..908505d 100644
--- a/luni/src/main/java/java/io/PipedReader.java
+++ b/luni/src/main/java/java/io/PipedReader.java
@@ -199,28 +199,21 @@
     }
 
     /**
-     * Reads at most {@code count} characters from this reader and stores them
+     * Reads up to {@code count} characters from this reader and stores them
      * in the character array {@code buffer} starting at {@code offset}. If
      * there is no data in the pipe, this method blocks until at least one byte
      * has been read, the end of the reader is detected or an exception is
      * thrown.
-     * <p>
-     * Separate threads should be used to read from a {@code PipedReader} and to
+     *
+     * <p>Separate threads should be used to read from a {@code PipedReader} and to
      * write to the connected {@link PipedWriter}. If the same thread is used, a
      * deadlock may occur.
      *
-     * @param buffer
-     *            the character array in which to store the characters read.
-     * @param offset
-     *            the initial position in {@code bytes} to store the characters
-     *            read from this reader.
-     * @param count
-     *            the maximum number of characters to store in {@code buffer}.
-     * @return the number of characters read or -1 if the end of the reader has
-     *         been reached.
+     * <p>Returns the number of characters read or -1 if the end of the reader has
+     * been reached.
+     *
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code count < 0}, or if {@code
-     *             offset + count} is greater than the size of {@code buffer}.
+     *     if {@code offset < 0 || count < 0 || offset + count > buffer.length}.
      * @throws InterruptedIOException
      *             if the thread reading from this reader is interrupted.
      * @throws IOException
@@ -228,8 +221,7 @@
      *             the thread writing to the connected writer is no longer
      *             alive.
      */
-    @Override
-    public synchronized int read(char[] buffer, int offset, int count) throws IOException {
+    @Override public synchronized int read(char[] buffer, int offset, int count) throws IOException {
         if (!isConnected) {
             throw new IOException("Pipe not connected");
         }
diff --git a/luni/src/main/java/java/io/PushbackInputStream.java b/luni/src/main/java/java/io/PushbackInputStream.java
index fa0df85..d7bebb1 100644
--- a/luni/src/main/java/java/io/PushbackInputStream.java
+++ b/luni/src/main/java/java/io/PushbackInputStream.java
@@ -147,42 +147,31 @@
     }
 
     /**
-     * Reads at most {@code length} bytes from this stream and stores them in
-     * the byte array {@code buffer} starting at {@code offset}. Bytes are read
+     * Reads up to {@code byteCount} bytes from this stream and stores them in
+     * the byte array {@code buffer} starting at {@code byteOffset}. Bytes are read
      * from the pushback buffer first, then from the source stream if more bytes
-     * are required. Blocks until {@code count} bytes have been read, the end of
-     * the source stream is detected or an exception is thrown.
+     * are required. Blocks until {@code byteCount} bytes have been read, the end of
+     * the source stream is detected or an exception is thrown. Returns the number of bytes read,
+     * or -1 if the end of the source stream has been reached.
      *
-     * @param buffer
-     *            the array in which to store the bytes read from this stream.
-     * @param offset
-     *            the initial position in {@code buffer} to store the bytes read
-     *            from this stream.
-     * @param length
-     *            the maximum number of bytes to store in {@code buffer}.
-     * @return the number of bytes read or -1 if the end of the source stream
-     *         has been reached.
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code length < 0}, or if
-     *             {@code offset + length} is greater than the length of
-     *             {@code buffer}.
+     *     if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > buffer.length}.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs while
      *             reading from this stream.
      * @throws NullPointerException
-     *             if {@code buffer} is {@code null}.
+     *             if {@code buffer == null}.
      */
     @Override
-    public int read(byte[] buffer, int offset, int length) throws IOException {
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
         if (buf == null) {
             throw streamClosed();
         }
-        Arrays.checkOffsetAndCount(buffer.length, offset, length);
-        int copiedBytes = 0, copyLength = 0, newOffset = offset;
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
+        int copiedBytes = 0, copyLength = 0, newOffset = byteOffset;
         // Are there pushback bytes available?
         if (pos < buf.length) {
-            copyLength = (buf.length - pos >= length) ? length : buf.length
-                    - pos;
+            copyLength = (buf.length - pos >= byteCount) ? byteCount : buf.length - pos;
             System.arraycopy(buf, pos, buffer, newOffset, copyLength);
             newOffset += copyLength;
             copiedBytes += copyLength;
@@ -190,10 +179,10 @@
             pos += copyLength;
         }
         // Have we copied enough?
-        if (copyLength == length) {
-            return length;
+        if (copyLength == byteCount) {
+            return byteCount;
         }
-        int inCopied = in.read(buffer, newOffset, length - copiedBytes);
+        int inCopied = in.read(buffer, newOffset, byteCount - copiedBytes);
         if (inCopied > 0) {
             return inCopied + copiedBytes;
         }
diff --git a/luni/src/main/java/java/io/PushbackReader.java b/luni/src/main/java/java/io/PushbackReader.java
index 2e3cf83..59e6644 100644
--- a/luni/src/main/java/java/io/PushbackReader.java
+++ b/luni/src/main/java/java/io/PushbackReader.java
@@ -155,26 +155,15 @@
     }
 
     /**
-     * Reads at most {@code length} bytes from this reader and stores them in
-     * byte array {@code buffer} starting at {@code offset}. Characters are
+     * Reads up to {@code count} characters from this reader and stores them in
+     * character array {@code buffer} starting at {@code offset}. Characters are
      * read from the pushback buffer first, then from the source reader if more
      * bytes are required. Blocks until {@code count} characters have been read,
      * the end of the source reader is detected or an exception is thrown.
+     * Returns the number of bytes read or -1 if the end of the source reader has been reached.
      *
-     * @param buffer
-     *            the array in which to store the characters read from this
-     *            reader.
-     * @param offset
-     *            the initial position in {@code buffer} to store the characters
-     *            read from this reader.
-     * @param count
-     *            the maximum number of bytes to store in {@code buffer}.
-     * @return the number of bytes read or -1 if the end of the source reader
-     *         has been reached.
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code count < 0}, or if
-     *             {@code offset + count} is greater than the length of
-     *             {@code buffer}.
+     *     if {@code offset < 0 || count < 0 || offset + count > buffer.length}.
      * @throws IOException
      *             if this reader is closed or another I/O error occurs while
      *             reading from this reader.
diff --git a/luni/src/main/java/java/io/RandomAccessFile.java b/luni/src/main/java/java/io/RandomAccessFile.java
index dde779e..a60da3e 100644
--- a/luni/src/main/java/java/io/RandomAccessFile.java
+++ b/luni/src/main/java/java/io/RandomAccessFile.java
@@ -260,11 +260,9 @@
      * byte array {@code buffer}. The maximum number of bytes read corresponds
      * to the size of {@code buffer}. Blocks until at least one byte has been
      * read, the end of the file is detected, or an exception is thrown.
+     * Returns the number of bytes actually read or -1 if the end of the file
+     * has been reached. See also {@link #readFully}.
      *
-     * @param buffer
-     *            the byte array in which to store the bytes read.
-     * @return the number of bytes actually read or -1 if the end of the file
-     *         has been reached.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      */
@@ -273,16 +271,15 @@
     }
 
     /**
-     * Reads at most {@code byteCount} bytes from the current position in this file
+     * Reads up to {@code byteCount} bytes from the current position in this file
      * and stores them in the byte array {@code buffer} starting at {@code
      * byteOffset}. Blocks until at least one byte has been
      * read, the end of the file is detected, or an exception is thrown.
+     * Returns the number of bytes actually read or -1 if the end of the stream has been reached.
+     * See also {@link #readFully}.
      *
-     * @return the number of bytes actually read or -1 if the end of the stream
-     *         has been reached.
      * @throws IndexOutOfBoundsException
-     *             if {@code byteOffset < 0} or {@code byteCount < 0}, or if {@code
-     *             byteOffset + byteCount} is greater than the size of {@code buffer}.
+     *     if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > buffer.length}.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      */
diff --git a/luni/src/main/java/java/io/Reader.java b/luni/src/main/java/java/io/Reader.java
index e947d08..8ef9a7c 100644
--- a/luni/src/main/java/java/io/Reader.java
+++ b/luni/src/main/java/java/io/Reader.java
@@ -131,39 +131,26 @@
 
     /**
      * Reads characters from this reader and stores them in the character array
-     * {@code buf} starting at offset 0. Returns the number of characters
+     * {@code buffer} starting at offset 0. Returns the number of characters
      * actually read or -1 if the end of the reader has been reached.
      *
-     * @param buf
-     *            character array to store the characters read.
-     * @return the number of characters read or -1 if the end of the reader has
-     *         been reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
      */
-    public int read(char[] buf) throws IOException {
-        return read(buf, 0, buf.length);
+    public int read(char[] buffer) throws IOException {
+        return read(buffer, 0, buffer.length);
     }
 
     /**
-     * Reads at most {@code count} characters from this reader and stores them
-     * at {@code offset} in the character array {@code buf}. Returns the number
+     * Reads up to {@code count} characters from this reader and stores them
+     * at {@code offset} in the character array {@code buffer}. Returns the number
      * of characters actually read or -1 if the end of the reader has been
      * reached.
      *
-     * @param buf
-     *            the character array to store the characters read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the characters
-     *            read from this reader.
-     * @param count
-     *            the maximum number of characters to read.
-     * @return the number of characters read or -1 if the end of the reader has
-     *         been reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
      */
-    public abstract int read(char[] buf, int offset, int count) throws IOException;
+    public abstract int read(char[] buffer, int offset, int count) throws IOException;
 
     /**
      * Indicates whether this reader is ready to be read without blocking.
diff --git a/luni/src/main/java/java/io/SequenceInputStream.java b/luni/src/main/java/java/io/SequenceInputStream.java
index 8333834..a328167 100644
--- a/luni/src/main/java/java/io/SequenceInputStream.java
+++ b/luni/src/main/java/java/io/SequenceInputStream.java
@@ -146,15 +146,15 @@
     }
 
     /**
-     * Reads at most {@code count} bytes from this sequence of input streams and
-     * stores them in the byte array {@code buffer} starting at {@code offset}.
+     * Reads up to {@code byteCount} bytes from this sequence of input streams and
+     * stores them in the byte array {@code buffer} starting at {@code byteOffset}.
      * Blocks only until at least 1 byte has been read, the end of the stream
      * has been reached, or an exception is thrown.
      * <p>
      * This SequenceInputStream shows the same behavior as other InputStreams.
      * To do this it will read only as many bytes as a call to read on the
      * current substream returns. If that call does not return as many bytes as
-     * requested by {@code count}, it will not retry to read more on its own
+     * requested by {@code byteCount}, it will not retry to read more on its own
      * because subsequent reads might block. This would violate the rule that
      * it will only block until at least one byte has been read.
      * <p>
@@ -162,32 +162,21 @@
      * will close that substream and start with the next one. If there are no
      * more substreams it will return -1.
      *
-     * @param buffer
-     *            the array in which to store the bytes read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the bytes read
-     *            from this stream.
-     * @param count
-     *            the maximum number of bytes to store in {@code buffer}.
-     * @return the number of bytes actually read; -1 if this sequence of streams
-     *         is closed or if the end of the last stream in the sequence has
-     *         been reached.
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code count < 0}, or if {@code
-     *             offset + count} is greater than the size of {@code buffer}.
+     *     if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > buffer.length}.
      * @throws IOException
      *             if an I/O error occurs.
      * @throws NullPointerException
-     *             if {@code buffer} is {@code null}.
+     *             if {@code buffer == null}.
      */
     @Override
-    public int read(byte[] buffer, int offset, int count) throws IOException {
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
         if (in == null) {
             return -1;
         }
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
         while (in != null) {
-            int result = in.read(buffer, offset, count);
+            int result = in.read(buffer, byteOffset, byteCount);
             if (result >= 0) {
                 return result;
             }
diff --git a/luni/src/main/java/java/io/StreamTokenizer.java b/luni/src/main/java/java/io/StreamTokenizer.java
index a16dc4b..a9e5373 100644
--- a/luni/src/main/java/java/io/StreamTokenizer.java
+++ b/luni/src/main/java/java/io/StreamTokenizer.java
@@ -155,13 +155,13 @@
     /**
      * Constructs a new {@code StreamTokenizer} with {@code is} as source input
      * stream. This constructor is deprecated; instead, the constructor that
-     * takes a {@code Reader} as an arugment should be used.
+     * takes a {@code Reader} as an argument should be used.
      *
      * @param is
      *            the source stream from which to parse tokens.
      * @throws NullPointerException
      *             if {@code is} is {@code null}.
-     * @deprecated Use {@link #StreamTokenizer(Reader)}
+     * @deprecated Use {@link #StreamTokenizer(Reader)} instead.
      */
     @Deprecated
     public StreamTokenizer(InputStream is) {
diff --git a/luni/src/main/java/java/io/StringBufferInputStream.java b/luni/src/main/java/java/io/StringBufferInputStream.java
index 1768abe..fb3fb73 100644
--- a/luni/src/main/java/java/io/StringBufferInputStream.java
+++ b/luni/src/main/java/java/io/StringBufferInputStream.java
@@ -23,7 +23,7 @@
  * A specialized {@link InputStream} that reads bytes from a {@code String} in
  * a sequential manner.
  *
- * @deprecated Use {@link StringReader}
+ * @deprecated Use {@link StringReader} instead.
  */
 @Deprecated
 public class StringBufferInputStream extends InputStream {
@@ -78,39 +78,18 @@
         return pos < count ? buffer.charAt(pos++) & 0xFF : -1;
     }
 
-    /**
-     * Reads at most {@code length} bytes from the source string and stores them
-     * in the byte array {@code b} starting at {@code offset}.
-     *
-     * @param buffer
-     *            the byte array in which to store the bytes read.
-     * @param offset
-     *            the initial position in {@code b} to store the bytes read from
-     *            this stream.
-     * @param length
-     *            the maximum number of bytes to store in {@code b}.
-     * @return the number of bytes actually read or -1 if the end of the source
-     *         string has been reached.
-     * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code length < 0}, or if
-     *             {@code offset + length} is greater than the length of
-     *             {@code b}.
-     * @throws NullPointerException
-     *             if {@code b} is {@code null}.
-     */
-    @Override
-    public synchronized int read(byte[] buffer, int offset, int length) {
+    @Override public synchronized int read(byte[] buffer, int byteOffset, int byteCount) {
         if (buffer == null) {
             throw new NullPointerException("buffer == null");
         }
-        Arrays.checkOffsetAndCount(buffer.length, offset, length);
-        if (length == 0) {
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
+        if (byteCount == 0) {
             return 0;
         }
 
-        int copylen = count - pos < length ? count - pos : length;
-        for (int i = 0; i < copylen; i++) {
-            buffer[offset + i] = (byte) this.buffer.charAt(pos + i);
+        int copylen = count - pos < byteCount ? count - pos : byteCount;
+        for (int i = 0; i < copylen; ++i) {
+            buffer[byteOffset + i] = (byte) this.buffer.charAt(pos + i);
         }
         pos += copylen;
         return copylen;
diff --git a/luni/src/main/java/java/io/StringReader.java b/luni/src/main/java/java/io/StringReader.java
index 5579d62..ebe6c83 100644
--- a/luni/src/main/java/java/io/StringReader.java
+++ b/luni/src/main/java/java/io/StringReader.java
@@ -131,39 +131,29 @@
     }
 
     /**
-     * Reads at most {@code len} characters from the source string and stores
-     * them at {@code offset} in the character array {@code buf}. Returns the
+     * Reads up to {@code count} characters from the source string and stores
+     * them at {@code offset} in the character array {@code buffer}. Returns the
      * number of characters actually read or -1 if the end of the source string
      * has been reached.
      *
-     * @param buf
-     *            the character array to store the characters read.
-     * @param offset
-     *            the initial position in {@code buffer} to store the characters
-     *            read from this reader.
-     * @param len
-     *            the maximum number of characters to read.
-     * @return the number of characters read or -1 if the end of the reader has
-     *         been reached.
      * @throws IndexOutOfBoundsException
-     *             if {@code offset < 0} or {@code len < 0}, or if
-     *             {@code offset + len} is greater than the size of {@code buf}.
+                if {@code offset < 0 || count < 0 || offset + count > buffer.length}.
      * @throws IOException
      *             if this reader is closed.
      */
     @Override
-    public int read(char[] buf, int offset, int len) throws IOException {
+    public int read(char[] buffer, int offset, int count) throws IOException {
         synchronized (lock) {
             checkNotClosed();
-            Arrays.checkOffsetAndCount(buf.length, offset, len);
-            if (len == 0) {
+            Arrays.checkOffsetAndCount(buffer.length, offset, count);
+            if (count == 0) {
                 return 0;
             }
             if (pos == this.count) {
                 return -1;
             }
-            int end = pos + len > this.count ? this.count : pos + len;
-            str.getChars(pos, end, buf, offset);
+            int end = pos + count > this.count ? this.count : pos + count;
+            str.getChars(pos, end, buffer, offset);
             int read = end - pos;
             pos = end;
             return read;
diff --git a/luni/src/main/java/java/lang/AssertionError.java b/luni/src/main/java/java/lang/AssertionError.java
index 077e57c..e00d8e6 100644
--- a/luni/src/main/java/java/lang/AssertionError.java
+++ b/luni/src/main/java/java/lang/AssertionError.java
@@ -35,7 +35,6 @@
     /**
      * Constructs a new {@code AssertionError} with the given detail message and cause.
      * @since 1.7
-     * @hide 1.7
      */
     public AssertionError(String detailMessage, Throwable cause) {
         super(detailMessage, cause);
diff --git a/luni/src/main/java/java/lang/AutoCloseable.java b/luni/src/main/java/java/lang/AutoCloseable.java
index b3133a9..df789e0 100644
--- a/luni/src/main/java/java/lang/AutoCloseable.java
+++ b/luni/src/main/java/java/lang/AutoCloseable.java
@@ -31,15 +31,10 @@
  * }</pre>
  *
  * @since 1.7
- * @hide 1.7
  */
 public interface AutoCloseable {
-
     /**
      * Closes the object and release any system resources it holds.
-     *
-     * <p>Unless the implementing class specifies otherwise, it is an error to
-     * call {@link #close} more than once.
      */
     void close() throws Exception;
 }
diff --git a/luni/src/main/java/java/lang/Boolean.java b/luni/src/main/java/java/lang/Boolean.java
index 2c8ffc8..fb02093 100644
--- a/luni/src/main/java/java/lang/Boolean.java
+++ b/luni/src/main/java/java/lang/Boolean.java
@@ -129,7 +129,6 @@
      * @return 0 if lhs = rhs, less than 0 if lhs &lt; rhs, and greater than 0 if lhs &gt; rhs.
      *         (Where true &gt; false.)
      * @since 1.7
-     * @hide 1.7
      */
     public static int compare(boolean lhs, boolean rhs) {
         return lhs == rhs ? 0 : lhs ? 1 : -1;
diff --git a/luni/src/main/java/java/lang/Byte.java b/luni/src/main/java/java/lang/Byte.java
index bd1a1e4..0ea50bf 100644
--- a/luni/src/main/java/java/lang/Byte.java
+++ b/luni/src/main/java/java/lang/Byte.java
@@ -113,7 +113,6 @@
      * Compares two {@code byte} values.
      * @return 0 if lhs = rhs, less than 0 if lhs &lt; rhs, and greater than 0 if lhs &gt; rhs.
      * @since 1.7
-     * @hide 1.7
      */
     public static int compare(byte lhs, byte rhs) {
         return lhs > rhs ? 1 : (lhs < rhs ? -1 : 0);
diff --git a/luni/src/main/java/java/lang/Character.java b/luni/src/main/java/java/lang/Character.java
index cf0ab84..5762bd4 100644
--- a/luni/src/main/java/java/lang/Character.java
+++ b/luni/src/main/java/java/lang/Character.java
@@ -522,66 +522,51 @@
      * Represents a subset of the Unicode character set.
      */
     public static class Subset {
-        String name;
+        private final String name;
 
         /**
          * Constructs a new {@code Subset}.
-         *
-         * @param string
-         *            this subset's name.
          */
-        protected Subset(String string) {
-            if (string == null) {
-                throw new NullPointerException("string == null");
+        protected Subset(String name) {
+            if (name == null) {
+                throw new NullPointerException("name == null");
             }
-            name = string;
+            this.name = name;
         }
 
         /**
-         * Compares this character subset with the specified object. Uses
-         * {@link java.lang.Object#equals(Object)} to do the comparison.
-         *
-         * @param object
-         *            the object to compare this character subset with.
-         * @return {@code true} if {@code object} is this subset, that is, if
-         *         {@code object == this}; {@code false} otherwise.
+         * Compares this character subset for identity with the specified object.
          */
-        @Override
-        public final boolean equals(Object object) {
-            return super.equals(object);
+        @Override public final boolean equals(Object object) {
+            return object == this;
         }
 
         /**
-         * Returns the integer hash code for this character subset.
-         *
-         * @return this subset's hash code, which is the hash code computed by
+         * Returns this subset's hash code, which is the hash code computed by
          *         {@link java.lang.Object#hashCode()}.
          */
-        @Override
-        public final int hashCode() {
+        @Override public final int hashCode() {
             return super.hashCode();
         }
 
         /**
-         * Returns the string representation of this subset.
-         *
-         * @return this subset's name.
+         * Returns this subset's name.
          */
-        @Override
-        public final String toString() {
+        @Override public final String toString() {
             return name;
         }
     }
 
     /**
-     * Represents a block of Unicode characters, as defined by the Unicode 4.0.1
-     * specification.
+     * Represents a block of Unicode characters. This class provides constants for various
+     * well-known blocks (but not all blocks) and methods for looking up a block
+     * by name {@link #forName} or by code point {@link #of}.
      *
      * @since 1.2
      */
     public static final class UnicodeBlock extends Subset {
         /**
-         * The &quot;Surrogates Area&quot; Unicode Block.
+         * The Surrogates Area Unicode block.
          *
          * @deprecated As of Java 5, this block has been replaced by
          *             {@link #HIGH_SURROGATES},
@@ -589,765 +574,669 @@
          *             {@link #LOW_SURROGATES}.
          */
         @Deprecated
-        public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA", 0x0, 0x0);
+        public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA");
+
+        /** The Basic Latin Unicode block. */
+        public static final UnicodeBlock BASIC_LATIN = new UnicodeBlock("BASIC_LATIN");
+
+        /** The Latin-1 Supplement Unicode block. */
+        public static final UnicodeBlock LATIN_1_SUPPLEMENT = new UnicodeBlock("LATIN_1_SUPPLEMENT");
+
+        /** The Latin Extended-A Unicode block. */
+        public static final UnicodeBlock LATIN_EXTENDED_A = new UnicodeBlock("LATIN_EXTENDED_A");
+
+        /** The Latin Extended-B Unicode block. */
+        public static final UnicodeBlock LATIN_EXTENDED_B = new UnicodeBlock("LATIN_EXTENDED_B");
+
+        /** The IPA Extensions Unicode block. */
+        public static final UnicodeBlock IPA_EXTENSIONS = new UnicodeBlock("IPA_EXTENSIONS");
+
+        /** The Spacing Modifier Letters Unicode block. */
+        public static final UnicodeBlock SPACING_MODIFIER_LETTERS = new UnicodeBlock("SPACING_MODIFIER_LETTERS");
+
+        /** The Combining Diacritical Marks Unicode block. */
+        public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS");
+
         /**
-         * The &quot;Basic Latin&quot; Unicode Block.
-         *
-         * @since 1.2
+         * The Greek and Coptic Unicode block. Previously referred to as Greek.
          */
-        public static final UnicodeBlock BASIC_LATIN = new UnicodeBlock("BASIC_LATIN", 0x0, 0x7f);
+        public static final UnicodeBlock GREEK = new UnicodeBlock("GREEK");
+
+        /** The Cyrillic Unicode block. */
+        public static final UnicodeBlock CYRILLIC = new UnicodeBlock("CYRILLIC");
+
         /**
-         * The &quot;Latin-1 Supplement&quot; Unicode Block.
-         *
-         * @since 1.2
+         * The Cyrillic Supplement Unicode block. Previously referred to as Cyrillic Supplementary.
          */
-        public static final UnicodeBlock LATIN_1_SUPPLEMENT = new UnicodeBlock("LATIN_1_SUPPLEMENT", 0x80, 0xff);
+        public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY");
+
+        /** The Armenian Unicode block. */
+        public static final UnicodeBlock ARMENIAN = new UnicodeBlock("ARMENIAN");
+
+        /** The Hebrew Unicode block. */
+        public static final UnicodeBlock HEBREW = new UnicodeBlock("HEBREW");
+
+        /** The Arabic Unicode block. */
+        public static final UnicodeBlock ARABIC = new UnicodeBlock("ARABIC");
+
+        /** The Syriac Unicode block. */
+        public static final UnicodeBlock SYRIAC = new UnicodeBlock("SYRIAC");
+
+        /** The Thaana Unicode block. */
+        public static final UnicodeBlock THAANA = new UnicodeBlock("THAANA");
+
+        /** The Devanagari Unicode block. */
+        public static final UnicodeBlock DEVANAGARI = new UnicodeBlock("DEVANAGARI");
+
+        /** The Bengali Unicode block. */
+        public static final UnicodeBlock BENGALI = new UnicodeBlock("BENGALI");
+
+        /** The Gurmukhi Unicode block. */
+        public static final UnicodeBlock GURMUKHI = new UnicodeBlock("GURMUKHI");
+
+        /** The Gujarati Unicode block. */
+        public static final UnicodeBlock GUJARATI = new UnicodeBlock("GUJARATI");
+
+        /** The Oriya Unicode block. */
+        public static final UnicodeBlock ORIYA = new UnicodeBlock("ORIYA");
+
+        /** The Tamil Unicode block. */
+        public static final UnicodeBlock TAMIL = new UnicodeBlock("TAMIL");
+
+        /** The Telugu Unicode block. */
+        public static final UnicodeBlock TELUGU = new UnicodeBlock("TELUGU");
+
+        /** The Kannada Unicode block. */
+        public static final UnicodeBlock KANNADA = new UnicodeBlock("KANNADA");
+
+        /** The Malayalam Unicode block. */
+        public static final UnicodeBlock MALAYALAM = new UnicodeBlock("MALAYALAM");
+
+        /** The Sinhala Unicode block. */
+        public static final UnicodeBlock SINHALA = new UnicodeBlock("SINHALA");
+
+        /** The Thai Unicode block. */
+        public static final UnicodeBlock THAI = new UnicodeBlock("THAI");
+
+        /** The Lao Unicode block. */
+        public static final UnicodeBlock LAO = new UnicodeBlock("LAO");
+
+        /** The Tibetan Unicode block. */
+        public static final UnicodeBlock TIBETAN = new UnicodeBlock("TIBETAN");
+
+        /** The Myanmar Unicode block. */
+        public static final UnicodeBlock MYANMAR = new UnicodeBlock("MYANMAR");
+
+        /** The Georgian Unicode block. */
+        public static final UnicodeBlock GEORGIAN = new UnicodeBlock("GEORGIAN");
+
+        /** The Hangul Jamo Unicode block. */
+        public static final UnicodeBlock HANGUL_JAMO = new UnicodeBlock("HANGUL_JAMO");
+
+        /** The Ethiopic Unicode block. */
+        public static final UnicodeBlock ETHIOPIC = new UnicodeBlock("ETHIOPIC");
+
+        /** The Cherokee Unicode block. */
+        public static final UnicodeBlock CHEROKEE = new UnicodeBlock("CHEROKEE");
+
+        /** The Unified Canadian Aboriginal Syllabics Unicode block. */
+        public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS");
+
+        /** The Ogham Unicode block. */
+        public static final UnicodeBlock OGHAM = new UnicodeBlock("OGHAM");
+
+        /** The Runic Unicode block. */
+        public static final UnicodeBlock RUNIC = new UnicodeBlock("RUNIC");
+
+        /** The Tagalog Unicode block. */
+        public static final UnicodeBlock TAGALOG = new UnicodeBlock("TAGALOG");
+
+        /** The Hanunoo Unicode block. */
+        public static final UnicodeBlock HANUNOO = new UnicodeBlock("HANUNOO");
+
+        /** The Buhid Unicode block. */
+        public static final UnicodeBlock BUHID = new UnicodeBlock("BUHID");
+
+        /** The Tagbanwa Unicode block. */
+        public static final UnicodeBlock TAGBANWA = new UnicodeBlock("TAGBANWA");
+
+        /** The Khmer Unicode block. */
+        public static final UnicodeBlock KHMER = new UnicodeBlock("KHMER");
+
+        /** The Mongolian Unicode block. */
+        public static final UnicodeBlock MONGOLIAN = new UnicodeBlock("MONGOLIAN");
+
+        /** The Limbu Unicode block. */
+        public static final UnicodeBlock LIMBU = new UnicodeBlock("LIMBU");
+
+        /** The Tai Le Unicode block. */
+        public static final UnicodeBlock TAI_LE = new UnicodeBlock("TAI_LE");
+
+        /** The Khmer Symbols Unicode block. */
+        public static final UnicodeBlock KHMER_SYMBOLS = new UnicodeBlock("KHMER_SYMBOLS");
+
+        /** The Phonetic Extensions Unicode block. */
+        public static final UnicodeBlock PHONETIC_EXTENSIONS = new UnicodeBlock("PHONETIC_EXTENSIONS");
+
+        /** The Latin Extended Additional Unicode block. */
+        public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL");
+
+        /** The Greek Extended Unicode block. */
+        public static final UnicodeBlock GREEK_EXTENDED = new UnicodeBlock("GREEK_EXTENDED");
+
+        /** The General Punctuation Unicode block. */
+        public static final UnicodeBlock GENERAL_PUNCTUATION = new UnicodeBlock("GENERAL_PUNCTUATION");
+
+        /** The Superscripts and Subscripts Unicode block. */
+        public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS");
+
+        /** The Currency Symbols Unicode block. */
+        public static final UnicodeBlock CURRENCY_SYMBOLS = new UnicodeBlock("CURRENCY_SYMBOLS");
+
         /**
-         * The &quot;Latin Extended-A&quot; Unicode Block.
-         *
-         * @since 1.2
+         * The Combining Diacritical Marks for Symbols Unicode
+         * Block. Previously referred to as Combining Marks for
+         * Symbols.
          */
-        public static final UnicodeBlock LATIN_EXTENDED_A = new UnicodeBlock("LATIN_EXTENDED_A", 0x100, 0x17f);
+        public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS");
+
+        /** The Letterlike Symbols Unicode block. */
+        public static final UnicodeBlock LETTERLIKE_SYMBOLS = new UnicodeBlock("LETTERLIKE_SYMBOLS");
+
+        /** The Number Forms Unicode block. */
+        public static final UnicodeBlock NUMBER_FORMS = new UnicodeBlock("NUMBER_FORMS");
+
+        /** The Arrows Unicode block. */
+        public static final UnicodeBlock ARROWS = new UnicodeBlock("ARROWS");
+
+        /** The Mathematical Operators Unicode block. */
+        public static final UnicodeBlock MATHEMATICAL_OPERATORS = new UnicodeBlock("MATHEMATICAL_OPERATORS");
+
+        /** The Miscellaneous Technical Unicode block. */
+        public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = new UnicodeBlock("MISCELLANEOUS_TECHNICAL");
+
+        /** The Control Pictures Unicode block. */
+        public static final UnicodeBlock CONTROL_PICTURES = new UnicodeBlock("CONTROL_PICTURES");
+
+        /** The Optical Character Recognition Unicode block. */
+        public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION");
+
+        /** The Enclosed Alphanumerics Unicode block. */
+        public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = new UnicodeBlock("ENCLOSED_ALPHANUMERICS");
+
+        /** The Box Drawing Unicode block. */
+        public static final UnicodeBlock BOX_DRAWING = new UnicodeBlock("BOX_DRAWING");
+
+        /** The Block Elements Unicode block. */
+        public static final UnicodeBlock BLOCK_ELEMENTS = new UnicodeBlock("BLOCK_ELEMENTS");
+
+        /** The Geometric Shapes Unicode block. */
+        public static final UnicodeBlock GEOMETRIC_SHAPES = new UnicodeBlock("GEOMETRIC_SHAPES");
+
+        /** The Miscellaneous Symbols Unicode block. */
+        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS");
+
+        /** The Dingbats Unicode block. */
+        public static final UnicodeBlock DINGBATS = new UnicodeBlock("DINGBATS");
+
+        /** The Miscellaneous Mathematical Symbols-A Unicode block. */
+        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A");
+
+        /** The Supplemental Arrows-A Unicode block. */
+        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = new UnicodeBlock("SUPPLEMENTAL_ARROWS_A");
+
+        /** The Braille Patterns Unicode block. */
+        public static final UnicodeBlock BRAILLE_PATTERNS = new UnicodeBlock("BRAILLE_PATTERNS");
+
+        /** The Supplemental Arrows-B Unicode block. */
+        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = new UnicodeBlock("SUPPLEMENTAL_ARROWS_B");
+
+        /** The Miscellaneous Mathematical Symbols-B Unicode block. */
+        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B");
+
+        /** The Supplemental Mathematical Operators Unicode block. */
+        public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS");
+
+        /** The Miscellaneous Symbols and Arrows Unicode block. */
+        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS");
+
+        /** The CJK Radicals Supplement Unicode block. */
+        public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = new UnicodeBlock("CJK_RADICALS_SUPPLEMENT");
+
+        /** The Kangxi Radicals Unicode block. */
+        public static final UnicodeBlock KANGXI_RADICALS = new UnicodeBlock("KANGXI_RADICALS");
+
+        /** The Ideographic Description Characters Unicode block. */
+        public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS");
+
+        /** The CJK Symbols and Punctuation Unicode block. */
+        public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION");
+
+        /** The Hiragana Unicode block. */
+        public static final UnicodeBlock HIRAGANA = new UnicodeBlock("HIRAGANA");
+
+        /** The Katakana Unicode block. */
+        public static final UnicodeBlock KATAKANA = new UnicodeBlock("KATAKANA");
+
+        /** The Bopomofo Unicode block. */
+        public static final UnicodeBlock BOPOMOFO = new UnicodeBlock("BOPOMOFO");
+
+        /** The Hangul Compatibility Jamo Unicode block. */
+        public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO");
+
+        /** The Kanbun Unicode block. */
+        public static final UnicodeBlock KANBUN = new UnicodeBlock("KANBUN");
+
+        /** The Bopomofo Extended Unicode block. */
+        public static final UnicodeBlock BOPOMOFO_EXTENDED = new UnicodeBlock("BOPOMOFO_EXTENDED");
+
+        /** The Katakana Phonetic Extensions Unicode block. */
+        public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS");
+
+        /** The Enclosed CJK Letters and Months Unicode block. */
+        public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS");
+
+        /** The CJK Compatibility Unicode block. */
+        public static final UnicodeBlock CJK_COMPATIBILITY = new UnicodeBlock("CJK_COMPATIBILITY");
+
+        /** The CJK Unified Ideographs Extension A Unicode block. */
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A");
+
+        /** The Yijing Hexagram Symbols Unicode block. */
+        public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS");
+
+        /** The CJK Unified Ideographs Unicode block. */
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS");
+
+        /** The Yi Syllables Unicode block. */
+        public static final UnicodeBlock YI_SYLLABLES = new UnicodeBlock("YI_SYLLABLES");
+
+        /** The Yi Radicals Unicode block. */
+        public static final UnicodeBlock YI_RADICALS = new UnicodeBlock("YI_RADICALS");
+
+        /** The Hangul Syllables Unicode block. */
+        public static final UnicodeBlock HANGUL_SYLLABLES = new UnicodeBlock("HANGUL_SYLLABLES");
+
         /**
-         * The &quot;Latin Extended-B&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock LATIN_EXTENDED_B = new UnicodeBlock("LATIN_EXTENDED_B", 0x180, 0x24f);
-        /**
-         * The &quot;IPA Extensions&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock IPA_EXTENSIONS = new UnicodeBlock("IPA_EXTENSIONS", 0x250, 0x2af);
-        /**
-         * The &quot;Spacing Modifier Letters&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock SPACING_MODIFIER_LETTERS = new UnicodeBlock("SPACING_MODIFIER_LETTERS", 0x2b0, 0x2ff);
-        /**
-         * The &quot;Combining Diacritical Marks&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS", 0x300, 0x36f);
-        /**
-         * The &quot;Greek and Coptic&quot; Unicode Block. Previously referred
-         * to as &quot;Greek&quot;.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock GREEK = new UnicodeBlock("GREEK", 0x370, 0x3ff);
-        /**
-         * The &quot;Cyrillic&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock CYRILLIC = new UnicodeBlock("CYRILLIC", 0x400, 0x4ff);
-        /**
-         * The &quot;Cyrillic Supplement&quot; Unicode Block. Previously
-         * referred to as &quot;Cyrillic Supplementary&quot;.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY", 0x500, 0x52f);
-        /**
-         * The &quot;Armenian&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock ARMENIAN = new UnicodeBlock("ARMENIAN", 0x530, 0x58f);
-        /**
-         * The &quot;Hebrew&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock HEBREW = new UnicodeBlock("HEBREW", 0x590, 0x5ff);
-        /**
-         * The &quot;Arabic&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock ARABIC = new UnicodeBlock("ARABIC", 0x600, 0x6ff);
-        /**
-         * The &quot;Syriac&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock SYRIAC = new UnicodeBlock("SYRIAC", 0x700, 0x74f);
-        /**
-         * The &quot;Thaana&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock THAANA = new UnicodeBlock("THAANA", 0x780, 0x7bf);
-        /**
-         * The &quot;Devanagari&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock DEVANAGARI = new UnicodeBlock("DEVANAGARI", 0x900, 0x97f);
-        /**
-         * The &quot;Bengali&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock BENGALI = new UnicodeBlock("BENGALI", 0x980, 0x9ff);
-        /**
-         * The &quot;Gurmukhi&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock GURMUKHI = new UnicodeBlock("GURMUKHI", 0xa00, 0xa7f);
-        /**
-         * The &quot;Gujarati&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock GUJARATI = new UnicodeBlock("GUJARATI", 0xa80, 0xaff);
-        /**
-         * The &quot;Oriya&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock ORIYA = new UnicodeBlock("ORIYA", 0xb00, 0xb7f);
-        /**
-         * The &quot;Tamil&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock TAMIL = new UnicodeBlock("TAMIL", 0xb80, 0xbff);
-        /**
-         * The &quot;Telugu&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock TELUGU = new UnicodeBlock("TELUGU", 0xc00, 0xc7f);
-        /**
-         * The &quot;Kannada&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock KANNADA = new UnicodeBlock("KANNADA", 0xc80, 0xcff);
-        /**
-         * The &quot;Malayalam&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock MALAYALAM = new UnicodeBlock("MALAYALAM", 0xd00, 0xd7f);
-        /**
-         * The &quot;Sinhala&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock SINHALA = new UnicodeBlock("SINHALA", 0xd80, 0xdff);
-        /**
-         * The &quot;Thai&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock THAI = new UnicodeBlock("THAI", 0xe00, 0xe7f);
-        /**
-         * The &quot;Lao&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock LAO = new UnicodeBlock("LAO", 0xe80, 0xeff);
-        /**
-         * The &quot;Tibetan&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock TIBETAN = new UnicodeBlock("TIBETAN", 0xf00, 0xfff);
-        /**
-         * The &quot;Myanmar&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock MYANMAR = new UnicodeBlock("MYANMAR", 0x1000, 0x109f);
-        /**
-         * The &quot;Georgian&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock GEORGIAN = new UnicodeBlock("GEORGIAN", 0x10a0, 0x10ff);
-        /**
-         * The &quot;Hangul Jamo&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock HANGUL_JAMO = new UnicodeBlock("HANGUL_JAMO", 0x1100, 0x11ff);
-        /**
-         * The &quot;Ethiopic&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock ETHIOPIC = new UnicodeBlock("ETHIOPIC", 0x1200, 0x137f);
-        /**
-         * The &quot;Cherokee&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock CHEROKEE = new UnicodeBlock("CHEROKEE", 0x13a0, 0x13ff);
-        /**
-         * The &quot;Unified Canadian Aboriginal Syllabics&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS", 0x1400, 0x167f);
-        /**
-         * The &quot;Ogham&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock OGHAM = new UnicodeBlock("OGHAM", 0x1680, 0x169f);
-        /**
-         * The &quot;Runic&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock RUNIC = new UnicodeBlock("RUNIC", 0x16a0, 0x16ff);
-        /**
-         * The &quot;Tagalog&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock TAGALOG = new UnicodeBlock("TAGALOG", 0x1700, 0x171f);
-        /**
-         * The &quot;Hanunoo&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock HANUNOO = new UnicodeBlock("HANUNOO", 0x1720, 0x173f);
-        /**
-         * The &quot;Buhid&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock BUHID = new UnicodeBlock("BUHID", 0x1740, 0x175f);
-        /**
-         * The &quot;Tagbanwa&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock TAGBANWA = new UnicodeBlock("TAGBANWA", 0x1760, 0x177f);
-        /**
-         * The &quot;Khmer&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock KHMER = new UnicodeBlock("KHMER", 0x1780, 0x17ff);
-        /**
-         * The &quot;Mongolian&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock MONGOLIAN = new UnicodeBlock("MONGOLIAN", 0x1800, 0x18af);
-        /**
-         * The &quot;Limbu&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock LIMBU = new UnicodeBlock("LIMBU", 0x1900, 0x194f);
-        /**
-         * The &quot;Tai Le&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock TAI_LE = new UnicodeBlock("TAI_LE", 0x1950, 0x197f);
-        /**
-         * The &quot;Khmer Symbols&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock KHMER_SYMBOLS = new UnicodeBlock("KHMER_SYMBOLS", 0x19e0, 0x19ff);
-        /**
-         * The &quot;Phonetic Extensions&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock PHONETIC_EXTENSIONS = new UnicodeBlock("PHONETIC_EXTENSIONS", 0x1d00, 0x1d7f);
-        /**
-         * The &quot;Latin Extended Additional&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL", 0x1e00, 0x1eff);
-        /**
-         * The &quot;Greek Extended&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock GREEK_EXTENDED = new UnicodeBlock("GREEK_EXTENDED", 0x1f00, 0x1fff);
-        /**
-         * The &quot;General Punctuation&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock GENERAL_PUNCTUATION = new UnicodeBlock("GENERAL_PUNCTUATION", 0x2000, 0x206f);
-        /**
-         * The &quot;Superscripts and Subscripts&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS", 0x2070, 0x209f);
-        /**
-         * The &quot;Currency Symbols&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock CURRENCY_SYMBOLS = new UnicodeBlock("CURRENCY_SYMBOLS", 0x20a0, 0x20cf);
-        /**
-         * The &quot;Combining Diacritical Marks for Symbols&quot; Unicode
-         * Block. Previously referred to as &quot;Combining Marks for
-         * Symbols&quot;.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS", 0x20d0, 0x20ff);
-        /**
-         * The &quot;Letterlike Symbols&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock LETTERLIKE_SYMBOLS = new UnicodeBlock("LETTERLIKE_SYMBOLS", 0x2100, 0x214f);
-        /**
-         * The &quot;Number Forms&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock NUMBER_FORMS = new UnicodeBlock("NUMBER_FORMS", 0x2150, 0x218f);
-        /**
-         * The &quot;Arrows&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock ARROWS = new UnicodeBlock("ARROWS", 0x2190, 0x21ff);
-        /**
-         * The &quot;Mathematical Operators&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock MATHEMATICAL_OPERATORS = new UnicodeBlock("MATHEMATICAL_OPERATORS", 0x2200, 0x22ff);
-        /**
-         * The &quot;Miscellaneous Technical&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = new UnicodeBlock("MISCELLANEOUS_TECHNICAL", 0x2300, 0x23ff);
-        /**
-         * The &quot;Control Pictures&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock CONTROL_PICTURES = new UnicodeBlock("CONTROL_PICTURES", 0x2400, 0x243f);
-        /**
-         * The &quot;Optical Character Recognition&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION", 0x2440, 0x245f);
-        /**
-         * The &quot;Enclosed Alphanumerics&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = new UnicodeBlock("ENCLOSED_ALPHANUMERICS", 0x2460, 0x24ff);
-        /**
-         * The &quot;Box Drawing&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock BOX_DRAWING = new UnicodeBlock("BOX_DRAWING", 0x2500, 0x257f);
-        /**
-         * The &quot;Block Elements&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock BLOCK_ELEMENTS = new UnicodeBlock("BLOCK_ELEMENTS", 0x2580, 0x259f);
-        /**
-         * The &quot;Geometric Shapes&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock GEOMETRIC_SHAPES = new UnicodeBlock("GEOMETRIC_SHAPES", 0x25a0, 0x25ff);
-        /**
-         * The &quot;Miscellaneous Symbols&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS", 0x2600, 0x26ff);
-        /**
-         * The &quot;Dingbats&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock DINGBATS = new UnicodeBlock("DINGBATS", 0x2700, 0x27bf);
-        /**
-         * The &quot;Miscellaneous Mathematical Symbols-A&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A", 0x27c0, 0x27ef);
-        /**
-         * The &quot;Supplemental Arrows-A&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = new UnicodeBlock("SUPPLEMENTAL_ARROWS_A", 0x27f0, 0x27ff);
-        /**
-         * The &quot;Braille Patterns&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock BRAILLE_PATTERNS = new UnicodeBlock("BRAILLE_PATTERNS", 0x2800, 0x28ff);
-        /**
-         * The &quot;Supplemental Arrows-B&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = new UnicodeBlock("SUPPLEMENTAL_ARROWS_B", 0x2900, 0x297f);
-        /**
-         * The &quot;Miscellaneous Mathematical Symbols-B&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B", 0x2980, 0x29ff);
-        /**
-         * The &quot;Supplemental Mathematical Operators&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS", 0x2a00, 0x2aff);
-        /**
-         * The &quot;Miscellaneous Symbols and Arrows&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS", 0x2b00, 0x2bff);
-        /**
-         * The &quot;CJK Radicals Supplement&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = new UnicodeBlock("CJK_RADICALS_SUPPLEMENT", 0x2e80, 0x2eff);
-        /**
-         * The &quot;Kangxi Radicals&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock KANGXI_RADICALS = new UnicodeBlock("KANGXI_RADICALS", 0x2f00, 0x2fdf);
-        /**
-         * The &quot;Ideographic Description Characters&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS", 0x2ff0, 0x2fff);
-        /**
-         * The &quot;CJK Symbols and Punctuation&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION", 0x3000, 0x303f);
-        /**
-         * The &quot;Hiragana&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock HIRAGANA = new UnicodeBlock("HIRAGANA", 0x3040, 0x309f);
-        /**
-         * The &quot;Katakana&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock KATAKANA = new UnicodeBlock("KATAKANA", 0x30a0, 0x30ff);
-        /**
-         * The &quot;Bopomofo&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock BOPOMOFO = new UnicodeBlock("BOPOMOFO", 0x3100, 0x312f);
-        /**
-         * The &quot;Hangul Compatibility Jamo&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO", 0x3130, 0x318f);
-        /**
-         * The &quot;Kanbun&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock KANBUN = new UnicodeBlock("KANBUN", 0x3190, 0x319f);
-        /**
-         * The &quot;Bopomofo Extended&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock BOPOMOFO_EXTENDED = new UnicodeBlock("BOPOMOFO_EXTENDED", 0x31a0, 0x31bf);
-        /**
-         * The &quot;Katakana Phonetic Extensions&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS", 0x31f0, 0x31ff);
-        /**
-         * The &quot;Enclosed CJK Letters and Months&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS", 0x3200, 0x32ff);
-        /**
-         * The &quot;CJK Compatibility&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock CJK_COMPATIBILITY = new UnicodeBlock("CJK_COMPATIBILITY", 0x3300, 0x33ff);
-        /**
-         * The &quot;CJK Unified Ideographs Extension A&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", 0x3400, 0x4dbf);
-        /**
-         * The &quot;Yijing Hexagram Symbols&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS", 0x4dc0, 0x4dff);
-        /**
-         * The &quot;CJK Unified Ideographs&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS", 0x4e00, 0x9fff);
-        /**
-         * The &quot;Yi Syllables&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock YI_SYLLABLES = new UnicodeBlock("YI_SYLLABLES", 0xa000, 0xa48f);
-        /**
-         * The &quot;Yi Radicals&quot; Unicode Block.
-         *
-         * @since 1.4
-         */
-        public static final UnicodeBlock YI_RADICALS = new UnicodeBlock("YI_RADICALS", 0xa490, 0xa4cf);
-        /**
-         * The &quot;Hangul Syllables&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock HANGUL_SYLLABLES = new UnicodeBlock("HANGUL_SYLLABLES", 0xac00, 0xd7af);
-        /**
-         * The &quot;High Surrogates&quot; Unicode Block. This block represents
+         * The High Surrogates Unicode block. This block represents
          * code point values in the high surrogate range 0xD800 to 0xDB7F
          */
-        public static final UnicodeBlock HIGH_SURROGATES = new UnicodeBlock("HIGH_SURROGATES", 0xd800, 0xdb7f);
+        public static final UnicodeBlock HIGH_SURROGATES = new UnicodeBlock("HIGH_SURROGATES");
+
         /**
-         * The &quot;High Private Use Surrogates&quot; Unicode Block. This block
+         * The High Private Use Surrogates Unicode block. This block
          * represents code point values in the high surrogate range 0xDB80 to
          * 0xDBFF
          */
-        public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES", 0xdb80, 0xdbff);
+        public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES");
+
         /**
-         * The &quot;Low Surrogates&quot; Unicode Block. This block represents
+         * The Low Surrogates Unicode block. This block represents
          * code point values in the low surrogate range 0xDC00 to 0xDFFF
          */
-        public static final UnicodeBlock LOW_SURROGATES = new UnicodeBlock("LOW_SURROGATES", 0xdc00, 0xdfff);
-        /**
-         * The &quot;Private Use Area&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock PRIVATE_USE_AREA = new UnicodeBlock("PRIVATE_USE_AREA", 0xe000, 0xf8ff);
-        /**
-         * The &quot;CJK Compatibility Ideographs&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS", 0xf900, 0xfaff);
-        /**
-         * The &quot;Alphabetic Presentation Forms&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS", 0xfb00, 0xfb4f);
-        /**
-         * The &quot;Arabic Presentation Forms-A&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A", 0xfb50, 0xfdff);
-        /**
-         * The &quot;Variation Selectors&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock VARIATION_SELECTORS = new UnicodeBlock("VARIATION_SELECTORS", 0xfe00, 0xfe0f);
-        /**
-         * The &quot;Combining Half Marks&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock COMBINING_HALF_MARKS = new UnicodeBlock("COMBINING_HALF_MARKS", 0xfe20, 0xfe2f);
-        /**
-         * The &quot;CJK Compatibility Forms&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = new UnicodeBlock("CJK_COMPATIBILITY_FORMS", 0xfe30, 0xfe4f);
-        /**
-         * The &quot;Small Form Variants&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock SMALL_FORM_VARIANTS = new UnicodeBlock("SMALL_FORM_VARIANTS", 0xfe50, 0xfe6f);
-        /**
-         * The &quot;Arabic Presentation Forms-B&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B", 0xfe70, 0xfeff);
-        /**
-         * The &quot;Halfwidth and Fullwidth Forms&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS", 0xff00, 0xffef);
-        /**
-         * The &quot;Specials&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock SPECIALS = new UnicodeBlock("SPECIALS", 0xfff0, 0xffff);
-        /**
-         * The &quot;Linear B Syllabary&quot; Unicode Block.
-         *
-         * @since 1.2
-         */
-        public static final UnicodeBlock LINEAR_B_SYLLABARY = new UnicodeBlock("LINEAR_B_SYLLABARY", 0x10000, 0x1007f);
-        /**
-         * The &quot;Linear B Ideograms&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock LINEAR_B_IDEOGRAMS = new UnicodeBlock("LINEAR_B_IDEOGRAMS", 0x10080, 0x100ff);
-        /**
-         * The &quot;Aegean Numbers&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock AEGEAN_NUMBERS = new UnicodeBlock("AEGEAN_NUMBERS", 0x10100, 0x1013f);
-        /**
-         * The &quot;Old Italic&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock OLD_ITALIC = new UnicodeBlock("OLD_ITALIC", 0x10300, 0x1032f);
-        /**
-         * The &quot;Gothic&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC", 0x10330, 0x1034f);
-        /**
-         * The &quot;Ugaritic&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC", 0x10380, 0x1039f);
-        /**
-         * The &quot;Deseret&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET", 0x10400, 0x1044f);
-        /**
-         * The &quot;Shavian&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN", 0x10450, 0x1047f);
-        /**
-         * The &quot;Osmanya&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA", 0x10480, 0x104af);
-        /**
-         * The &quot;Cypriot Syllabary&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock CYPRIOT_SYLLABARY = new UnicodeBlock("CYPRIOT_SYLLABARY", 0x10800, 0x1083f);
-        /**
-         * The &quot;Byzantine Musical Symbols&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS", 0x1d000, 0x1d0ff);
-        /**
-         * The &quot;Musical Symbols&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock MUSICAL_SYMBOLS = new UnicodeBlock("MUSICAL_SYMBOLS", 0x1d100, 0x1d1ff);
-        /**
-         * The &quot;Tai Xuan Jing Symbols&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = new UnicodeBlock("TAI_XUAN_JING_SYMBOLS", 0x1d300, 0x1d35f);
-        /**
-         * The &quot;Mathematical Alphanumeric Symbols&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS", 0x1d400, 0x1d7ff);
-        /**
-         * The &quot;CJK Unified Ideographs Extension B&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B", 0x20000, 0x2a6df);
-        /**
-         * The &quot;CJK Compatibility Ideographs Supplement&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT", 0x2f800, 0x2fa1f);
-        /**
-         * The &quot;Tags&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS", 0xe0000, 0xe007f);
-        /**
-         * The &quot;Variation Selectors Supplement&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT", 0xe0100, 0xe01ef);
-        /**
-         * The &quot;Supplementary Private Use Area-A&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A", 0xf0000, 0xfffff);
-        /**
-         * The &quot;Supplementary Private Use Area-B&quot; Unicode Block.
-         *
-         * @since 1.5
-         */
-        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B", 0x100000, 0x10ffff);
+        public static final UnicodeBlock LOW_SURROGATES = new UnicodeBlock("LOW_SURROGATES");
+
+        /** The Private Use Area Unicode block. */
+        public static final UnicodeBlock PRIVATE_USE_AREA = new UnicodeBlock("PRIVATE_USE_AREA");
+
+        /** The CJK Compatibility Ideographs Unicode block. */
+        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS");
+
+        /** The Alphabetic Presentation Forms Unicode block. */
+        public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS");
+
+        /** The Arabic Presentation Forms-A Unicode block. */
+        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A");
+
+        /** The Variation Selectors Unicode block. */
+        public static final UnicodeBlock VARIATION_SELECTORS = new UnicodeBlock("VARIATION_SELECTORS");
+
+        /** The Combining Half Marks Unicode block. */
+        public static final UnicodeBlock COMBINING_HALF_MARKS = new UnicodeBlock("COMBINING_HALF_MARKS");
+
+        /** The CJK Compatibility Forms Unicode block. */
+        public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = new UnicodeBlock("CJK_COMPATIBILITY_FORMS");
+
+        /** The Small Form Variants Unicode block. */
+        public static final UnicodeBlock SMALL_FORM_VARIANTS = new UnicodeBlock("SMALL_FORM_VARIANTS");
+
+        /** The Arabic Presentation Forms-B Unicode block. */
+        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B");
+
+        /** The Halfwidth and Fullwidth Forms Unicode block. */
+        public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS");
+
+        /** The Specials Unicode block. */
+        public static final UnicodeBlock SPECIALS = new UnicodeBlock("SPECIALS");
+
+        /** The Linear B Syllabary Unicode block. */
+        public static final UnicodeBlock LINEAR_B_SYLLABARY = new UnicodeBlock("LINEAR_B_SYLLABARY");
+
+        /** The Linear B Ideograms Unicode block. */
+        public static final UnicodeBlock LINEAR_B_IDEOGRAMS = new UnicodeBlock("LINEAR_B_IDEOGRAMS");
+
+        /** The Aegean Numbers Unicode block. */
+        public static final UnicodeBlock AEGEAN_NUMBERS = new UnicodeBlock("AEGEAN_NUMBERS");
+
+        /** The Old Italic Unicode block. */
+        public static final UnicodeBlock OLD_ITALIC = new UnicodeBlock("OLD_ITALIC");
+
+        /** The Gothic Unicode block. */
+        public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC");
+
+        /** The Ugaritic Unicode block. */
+        public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC");
+
+        /** The Deseret Unicode block. */
+        public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET");
+
+        /** The Shavian Unicode block. */
+        public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN");
+
+        /** The Osmanya Unicode block. */
+        public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA");
+
+        /** The Cypriot Syllabary Unicode block. */
+        public static final UnicodeBlock CYPRIOT_SYLLABARY = new UnicodeBlock("CYPRIOT_SYLLABARY");
+
+        /** The Byzantine Musical Symbols Unicode block. */
+        public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS");
+
+        /** The Musical Symbols Unicode block. */
+        public static final UnicodeBlock MUSICAL_SYMBOLS = new UnicodeBlock("MUSICAL_SYMBOLS");
+
+        /** The Tai Xuan Jing Symbols Unicode block. */
+        public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = new UnicodeBlock("TAI_XUAN_JING_SYMBOLS");
+
+        /** The Mathematical Alphanumeric Symbols Unicode block. */
+        public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS");
+
+        /** The CJK Unified Ideographs Extension B Unicode block. */
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B");
+
+        /** The CJK Compatibility Ideographs Supplement Unicode block. */
+        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT");
+
+        /** The Tags Unicode block. */
+        public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS");
+
+        /** The Variation Selectors Supplement Unicode block. */
+        public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT");
+
+        /** The Supplementary Private Use Area-A Unicode block. */
+        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A");
+
+        /** The Supplementary Private Use Area-B Unicode block. */
+        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B");
+
+        // Unicode 4.1.
+
+        /** The Ancient Greek Musical Notation Unicode 4.1 block. */
+        public static final UnicodeBlock ANCIENT_GREEK_MUSICAL_NOTATION = new UnicodeBlock("ANCIENT_GREEK_MUSICAL_NOTATION");
+
+        /** The Ancient Greek Numbers Unicode 4.1 block. */
+        public static final UnicodeBlock ANCIENT_GREEK_NUMBERS = new UnicodeBlock("ANCIENT_GREEK_NUMBERS");
+
+        /** The Arabic Supplement Unicode 4.1 block. */
+        public static final UnicodeBlock ARABIC_SUPPLEMENT = new UnicodeBlock("ARABIC_SUPPLEMENT");
+
+        /** The Buginese Unicode 4.1 block. */
+        public static final UnicodeBlock BUGINESE = new UnicodeBlock("BUGINESE");
+
+        /** The CJK Strokes Unicode 4.1 block. */
+        public static final UnicodeBlock CJK_STROKES = new UnicodeBlock("CJK_STROKES");
+
+        /** The Combining Diacritical Marks Supplement Unicode 4.1 block. */
+        public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS_SUPPLEMENT = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS_SUPPLEMENT");
+
+        /** The Coptic Unicode 4.1 block. */
+        public static final UnicodeBlock COPTIC = new UnicodeBlock("COPTIC");
+
+        /** The Ethiopic Extended Unicode 4.1 block. */
+        public static final UnicodeBlock ETHIOPIC_EXTENDED = new UnicodeBlock("ETHIOPIC_EXTENDED");
+
+        /** The Ethiopic Supplement Unicode 4.1 block. */
+        public static final UnicodeBlock ETHIOPIC_SUPPLEMENT = new UnicodeBlock("ETHIOPIC_SUPPLEMENT");
+
+        /** The Georgian Supplement Unicode 4.1 block. */
+        public static final UnicodeBlock GEORGIAN_SUPPLEMENT = new UnicodeBlock("GEORGIAN_SUPPLEMENT");
+
+        /** The Glagolitic Unicode 4.1 block. */
+        public static final UnicodeBlock GLAGOLITIC = new UnicodeBlock("GLAGOLITIC");
+
+        /** The Kharoshthi Unicode 4.1 block. */
+        public static final UnicodeBlock KHAROSHTHI = new UnicodeBlock("KHAROSHTHI");
+
+        /** The Modifier Tone Letters Unicode 4.1 block. */
+        public static final UnicodeBlock MODIFIER_TONE_LETTERS = new UnicodeBlock("MODIFIER_TONE_LETTERS");
+
+        /** The New Tai Lue Unicode 4.1 block. */
+        public static final UnicodeBlock NEW_TAI_LUE = new UnicodeBlock("NEW_TAI_LUE");
+
+        /** The Old Persian Unicode 4.1 block. */
+        public static final UnicodeBlock OLD_PERSIAN = new UnicodeBlock("OLD_PERSIAN");
+
+        /** The Phonetic Extensions Supplement Unicode 4.1 block. */
+        public static final UnicodeBlock PHONETIC_EXTENSIONS_SUPPLEMENT = new UnicodeBlock("PHONETIC_EXTENSIONS_SUPPLEMENT");
+
+        /** The Supplemental Punctuation Unicode 4.1 block. */
+        public static final UnicodeBlock SUPPLEMENTAL_PUNCTUATION = new UnicodeBlock("SUPPLEMENTAL_PUNCTUATION");
+
+        /** The Syloti Nagri Unicode 4.1 block. */
+        public static final UnicodeBlock SYLOTI_NAGRI = new UnicodeBlock("SYLOTI_NAGRI");
+
+        /** The Tifinagh Unicode 4.1 block. */
+        public static final UnicodeBlock TIFINAGH = new UnicodeBlock("TIFINAGH");
+
+        /** The Vertical Forms Unicode 4.1 block. */
+        public static final UnicodeBlock VERTICAL_FORMS = new UnicodeBlock("VERTICAL_FORMS");
+
+        // Unicode 5.0.
+
+        /** The NKo Unicode 5.0 block. */
+        public static final UnicodeBlock NKO = new UnicodeBlock("NKO");
+
+        /** The Balinese Unicode 5.0 block. */
+        public static final UnicodeBlock BALINESE = new UnicodeBlock("BALINESE");
+
+        /** The Latin Extended C Unicode 5.0 block. */
+        public static final UnicodeBlock LATIN_EXTENDED_C = new UnicodeBlock("LATIN_EXTENDED_C");
+
+        /** The Latin Extended D Unicode 5.0 block. */
+        public static final UnicodeBlock LATIN_EXTENDED_D = new UnicodeBlock("LATIN_EXTENDED_D");
+
+        /** The Phags-pa Unicode 5.0 block. */
+        public static final UnicodeBlock PHAGS_PA = new UnicodeBlock("PHAGS_PA");
+
+        /** The Phoenician Unicode 5.0 block. */
+        public static final UnicodeBlock PHOENICIAN = new UnicodeBlock("PHOENICIAN");
+
+        /** The Cuneiform Unicode 5.0 block. */
+        public static final UnicodeBlock CUNEIFORM = new UnicodeBlock("CUNEIFORM");
+
+        /** The Cuneiform Numbers And Punctuation Unicode 5.0 block. */
+        public static final UnicodeBlock CUNEIFORM_NUMBERS_AND_PUNCTUATION = new UnicodeBlock("CUNEIFORM_NUMBERS_AND_PUNCTUATION");
+
+        /** The Counting Rod Numerals Unicode 5.0 block. */
+        public static final UnicodeBlock COUNTING_ROD_NUMERALS = new UnicodeBlock("COUNTING_ROD_NUMERALS");
+
+        // Unicode 5.1.
+
+        /** The Sudanese Unicode 5.1 block. */
+        public static final UnicodeBlock SUNDANESE = new UnicodeBlock("SUNDANESE");
+
+        /** The Lepcha Unicode 5.1 block. */
+        public static final UnicodeBlock LEPCHA = new UnicodeBlock("LEPCHA");
+
+        /** The Ol Chiki Unicode 5.1 block. */
+        public static final UnicodeBlock OL_CHIKI = new UnicodeBlock("OL_CHIKI");
+
+        /** The Cyrillic Extended-A Unicode 5.1 block. */
+        public static final UnicodeBlock CYRILLIC_EXTENDED_A = new UnicodeBlock("CYRILLIC_EXTENDED_A");
+
+        /** The Vai Unicode 5.1 block. */
+        public static final UnicodeBlock VAI = new UnicodeBlock("VAI");
+
+        /** The Cyrillic Extended-B Unicode 5.1 block. */
+        public static final UnicodeBlock CYRILLIC_EXTENDED_B = new UnicodeBlock("CYRILLIC_EXTENDED_B");
+
+        /** The Saurashtra Unicode 5.1 block. */
+        public static final UnicodeBlock SAURASHTRA = new UnicodeBlock("SAURASHTRA");
+
+        /** The Kayah Li Unicode 5.1 block. */
+        public static final UnicodeBlock KAYAH_LI = new UnicodeBlock("KAYAH_LI");
+
+        /** The Rejang Unicode 5.1 block. */
+        public static final UnicodeBlock REJANG = new UnicodeBlock("REJANG");
+
+        /** The Cham Unicode 5.1 block. */
+        public static final UnicodeBlock CHAM = new UnicodeBlock("CHAM");
+
+        /** The Ancient Symbols Unicode 5.1 block. */
+        public static final UnicodeBlock ANCIENT_SYMBOLS = new UnicodeBlock("ANCIENT_SYMBOLS");
+
+        /** The Phaistos Disc Unicode 5.1 block. */
+        public static final UnicodeBlock PHAISTOS_DISC = new UnicodeBlock("PHAISTOS_DISC");
+
+        /** The Lycian Unicode 5.1 block. */
+        public static final UnicodeBlock LYCIAN = new UnicodeBlock("LYCIAN");
+
+        /** The Carian Unicode 5.1 block. */
+        public static final UnicodeBlock CARIAN = new UnicodeBlock("CARIAN");
+
+        /** The Lydian Unicode 5.1 block. */
+        public static final UnicodeBlock LYDIAN = new UnicodeBlock("LYDIAN");
+
+        /** The Mahjong Tiles Unicode 5.1 block. */
+        public static final UnicodeBlock MAHJONG_TILES = new UnicodeBlock("MAHJONG_TILES");
+
+        /** The Domino Tiles Unicode 5.1 block. */
+        public static final UnicodeBlock DOMINO_TILES = new UnicodeBlock("DOMINO_TILES");
+
+        // Unicode 5.2.
+
+        /** The Samaritan Unicode 5.2 block. */
+        public static final UnicodeBlock SAMARITAN = new UnicodeBlock("SAMARITAN");
+
+        /** The Unified Canadian Aboriginal Syllabics Expanded Unicode 5.2 block. */
+        public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED");
+
+        /** The Tai Tham Unicode 5.2 block. */
+        public static final UnicodeBlock TAI_THAM = new UnicodeBlock("TAI_THAM");
+
+        /** The Vedic Extensions Unicode 5.2 block. */
+        public static final UnicodeBlock VEDIC_EXTENSIONS = new UnicodeBlock("VEDIC_EXTENSIONS");
+
+        /** The Lisu Extensions Unicode 5.2 block. */
+        public static final UnicodeBlock LISU = new UnicodeBlock("LISU");
+
+        /** The Bamum Extensions Unicode 5.2 block. */
+        public static final UnicodeBlock BAMUM = new UnicodeBlock("BAMUM");
+
+        /** The Common Indic Number Forms Unicode 5.2 block. */
+        public static final UnicodeBlock COMMON_INDIC_NUMBER_FORMS = new UnicodeBlock("COMMON_INDIC_NUMBER_FORMS");
+
+        /** The Devanagari Extended Unicode 5.2 block. */
+        public static final UnicodeBlock DEVANAGARI_EXTENDED = new UnicodeBlock("DEVANAGARI_EXTENDED");
+
+        /** The Hangul Jamo Extended-A Unicode 5.2 block. */
+        public static final UnicodeBlock HANGUL_JAMO_EXTENDED_A = new UnicodeBlock("HANGUL_JAMO_EXTENDED_A");
+
+        /** The Javanese Unicode 5.2 block. */
+        public static final UnicodeBlock JAVANESE = new UnicodeBlock("JAVANESE");
+
+        /** The Myanmar Extended-A Unicode 5.2 block. */
+        public static final UnicodeBlock MYANMAR_EXTENDED_A = new UnicodeBlock("MYANMAR_EXTENDED_A");
+
+        /** The Tai Viet Unicode 5.2 block. */
+        public static final UnicodeBlock TAI_VIET = new UnicodeBlock("TAI_VIET");
+
+        /** The Meetei Mayek Unicode 5.2 block. */
+        public static final UnicodeBlock MEETEI_MAYEK = new UnicodeBlock("MEETEI_MAYEK");
+
+        /** The Hangul Jamo Extended-B Unicode 5.2 block. */
+        public static final UnicodeBlock HANGUL_JAMO_EXTENDED_B = new UnicodeBlock("HANGUL_JAMO_EXTENDED_B");
+
+        /** The Imperial Aramaic Unicode 5.2 block. */
+        public static final UnicodeBlock IMPERIAL_ARAMAIC = new UnicodeBlock("IMPERIAL_ARAMAIC");
+
+        /** The Old South Arabian Unicode 5.2 block. */
+        public static final UnicodeBlock OLD_SOUTH_ARABIAN = new UnicodeBlock("OLD_SOUTH_ARABIAN");
+
+        /** The Avestan Unicode 5.2 block. */
+        public static final UnicodeBlock AVESTAN = new UnicodeBlock("AVESTAN");
+
+        /** The Inscriptional Pathian Unicode 5.2 block. */
+        public static final UnicodeBlock INSCRIPTIONAL_PARTHIAN = new UnicodeBlock("INSCRIPTIONAL_PARTHIAN");
+
+        /** The Inscriptional Pahlavi Unicode 5.2 block. */
+        public static final UnicodeBlock INSCRIPTIONAL_PAHLAVI = new UnicodeBlock("INSCRIPTIONAL_PAHLAVI");
+
+        /** The Old Turkic Unicode 5.2 block. */
+        public static final UnicodeBlock OLD_TURKIC = new UnicodeBlock("OLD_TURKIC");
+
+        /** The Rumi Numeral Symbols Unicode 5.2 block. */
+        public static final UnicodeBlock RUMI_NUMERAL_SYMBOLS = new UnicodeBlock("RUMI_NUMERAL_SYMBOLS");
+
+        /** The Kaithi Unicode 5.2 block. */
+        public static final UnicodeBlock KAITHI = new UnicodeBlock("KAITHI");
+
+        /** The Egyptian Hieroglyphs Unicode 5.2 block. */
+        public static final UnicodeBlock EGYPTIAN_HIEROGLYPHS = new UnicodeBlock("EGYPTIAN_HIEROGLYPHS");
+
+        /** The Enclosed Alphanumeric Supplement Unicode 5.2 block. */
+        public static final UnicodeBlock ENCLOSED_ALPHANUMERIC_SUPPLEMENT = new UnicodeBlock("ENCLOSED_ALPHANUMERIC_SUPPLEMENT");
+
+        /** The Enclosed Ideographic Supplement Unicode 5.2 block. */
+        public static final UnicodeBlock ENCLOSED_IDEOGRAPHIC_SUPPLEMENT = new UnicodeBlock("ENCLOSED_IDEOGRAPHIC_SUPPLEMENT");
+
+        /** The CJK Unified Ideographs Unicode 5.2 block. */
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C");
+
+        // Unicode 6.0.
+
+        /** The Mandaic Unicode 6.0 block. */
+        public static final UnicodeBlock MANDAIC = new UnicodeBlock("MANDAIC");
+
+        /** The Batak Unicode 6.0 block. */
+        public static final UnicodeBlock BATAK = new UnicodeBlock("BATAK");
+
+        /** The Ethiopic Extended-A Unicode 6.0 block. */
+        public static final UnicodeBlock ETHIOPIC_EXTENDED_A = new UnicodeBlock("ETHIOPIC_EXTENDED_A");
+
+        /** The Brahmi Unicode 6.0 block. */
+        public static final UnicodeBlock BRAHMI = new UnicodeBlock("BRAHMI");
+
+        /** The Bamum Supplement Unicode 6.0 block. */
+        public static final UnicodeBlock BAMUM_SUPPLEMENT = new UnicodeBlock("BAMUM_SUPPLEMENT");
+
+        /** The Kana Supplement Unicode 6.0 block. */
+        public static final UnicodeBlock KANA_SUPPLEMENT = new UnicodeBlock("KANA_SUPPLEMENT");
+
+        /** The Playing Cards Supplement Unicode 6.0 block. */
+        public static final UnicodeBlock PLAYING_CARDS = new UnicodeBlock("PLAYING_CARDS");
+
+        /** The Miscellaneous Symbols And Pictographs Supplement Unicode 6.0 block. */
+        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS");
+
+        /** The Emoticons Unicode 6.0 block. */
+        public static final UnicodeBlock EMOTICONS = new UnicodeBlock("EMOTICONS");
+
+        /** The Transport And Map Symbols Unicode 6.0 block. */
+        public static final UnicodeBlock TRANSPORT_AND_MAP_SYMBOLS = new UnicodeBlock("TRANSPORT_AND_MAP_SYMBOLS");
+
+        /** The Alchemical Symbols Unicode 6.0 block. */
+        public static final UnicodeBlock ALCHEMICAL_SYMBOLS = new UnicodeBlock("ALCHEMICAL_SYMBOLS");
+
+        /** The CJK Unified Ideographs Extension-D Unicode 6.0 block. */
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D");
 
         /*
-         * All of the UnicodeBlocks with valid ranges in ascending order.
+         * All of the UnicodeBlocks above, in the icu4c UBlock enum order.
          */
         private static UnicodeBlock[] BLOCKS = new UnicodeBlock[] {
-            null,
+            null, // icu4c numbers blocks starting at 1, so index 0 should be null.
+
             UnicodeBlock.BASIC_LATIN,
             UnicodeBlock.LATIN_1_SUPPLEMENT,
             UnicodeBlock.LATIN_EXTENDED_A,
@@ -1435,6 +1324,8 @@
             UnicodeBlock.ARABIC_PRESENTATION_FORMS_B,
             UnicodeBlock.SPECIALS,
             UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS,
+
+            // Unicode 3.1.
             UnicodeBlock.OLD_ITALIC,
             UnicodeBlock.GOTHIC,
             UnicodeBlock.DESERET,
@@ -1444,6 +1335,8 @@
             UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B,
             UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT,
             UnicodeBlock.TAGS,
+
+            // Unicode 3.2.
             UnicodeBlock.CYRILLIC_SUPPLEMENTARY,
             UnicodeBlock.TAGALOG,
             UnicodeBlock.HANUNOO,
@@ -1458,6 +1351,8 @@
             UnicodeBlock.VARIATION_SELECTORS,
             UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_A,
             UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_B,
+
+            // Unicode 4.0.
             UnicodeBlock.LIMBU,
             UnicodeBlock.TAI_LE,
             UnicodeBlock.KHMER_SYMBOLS,
@@ -1472,32 +1367,122 @@
             UnicodeBlock.OSMANYA,
             UnicodeBlock.CYPRIOT_SYLLABARY,
             UnicodeBlock.TAI_XUAN_JING_SYMBOLS,
-            UnicodeBlock.VARIATION_SELECTORS_SUPPLEMENT
+            UnicodeBlock.VARIATION_SELECTORS_SUPPLEMENT,
+
+            // Unicode 4.1.
+            UnicodeBlock.ANCIENT_GREEK_MUSICAL_NOTATION,
+            UnicodeBlock.ANCIENT_GREEK_NUMBERS,
+            UnicodeBlock.ARABIC_SUPPLEMENT,
+            UnicodeBlock.BUGINESE,
+            UnicodeBlock.CJK_STROKES,
+            UnicodeBlock.COMBINING_DIACRITICAL_MARKS_SUPPLEMENT,
+            UnicodeBlock.COPTIC,
+            UnicodeBlock.ETHIOPIC_EXTENDED,
+            UnicodeBlock.ETHIOPIC_SUPPLEMENT,
+            UnicodeBlock.GEORGIAN_SUPPLEMENT,
+            UnicodeBlock.GLAGOLITIC,
+            UnicodeBlock.KHAROSHTHI,
+            UnicodeBlock.MODIFIER_TONE_LETTERS,
+            UnicodeBlock.NEW_TAI_LUE,
+            UnicodeBlock.OLD_PERSIAN,
+            UnicodeBlock.PHONETIC_EXTENSIONS_SUPPLEMENT,
+            UnicodeBlock.SUPPLEMENTAL_PUNCTUATION,
+            UnicodeBlock.SYLOTI_NAGRI,
+            UnicodeBlock.TIFINAGH,
+            UnicodeBlock.VERTICAL_FORMS,
+
+            // Unicode 5.0.
+            UnicodeBlock.NKO,
+            UnicodeBlock.BALINESE,
+            UnicodeBlock.LATIN_EXTENDED_C,
+            UnicodeBlock.LATIN_EXTENDED_D,
+            UnicodeBlock.PHAGS_PA,
+            UnicodeBlock.PHOENICIAN,
+            UnicodeBlock.CUNEIFORM,
+            UnicodeBlock.CUNEIFORM_NUMBERS_AND_PUNCTUATION,
+            UnicodeBlock.COUNTING_ROD_NUMERALS,
+
+            // Unicode 5.1.
+            UnicodeBlock.SUNDANESE,
+            UnicodeBlock.LEPCHA,
+            UnicodeBlock.OL_CHIKI,
+            UnicodeBlock.CYRILLIC_EXTENDED_A,
+            UnicodeBlock.VAI,
+            UnicodeBlock.CYRILLIC_EXTENDED_B,
+            UnicodeBlock.SAURASHTRA,
+            UnicodeBlock.KAYAH_LI,
+            UnicodeBlock.REJANG,
+            UnicodeBlock.CHAM,
+            UnicodeBlock.ANCIENT_SYMBOLS,
+            UnicodeBlock.PHAISTOS_DISC,
+            UnicodeBlock.LYCIAN,
+            UnicodeBlock.CARIAN,
+            UnicodeBlock.LYDIAN,
+            UnicodeBlock.MAHJONG_TILES,
+            UnicodeBlock.DOMINO_TILES,
+
+            // Unicode 5.2.
+            UnicodeBlock.SAMARITAN,
+            UnicodeBlock.UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED,
+            UnicodeBlock.TAI_THAM,
+            UnicodeBlock.VEDIC_EXTENSIONS,
+            UnicodeBlock.LISU,
+            UnicodeBlock.BAMUM,
+            UnicodeBlock.COMMON_INDIC_NUMBER_FORMS,
+            UnicodeBlock.DEVANAGARI_EXTENDED,
+            UnicodeBlock.HANGUL_JAMO_EXTENDED_A,
+            UnicodeBlock.JAVANESE,
+            UnicodeBlock.MYANMAR_EXTENDED_A,
+            UnicodeBlock.TAI_VIET,
+            UnicodeBlock.MEETEI_MAYEK,
+            UnicodeBlock.HANGUL_JAMO_EXTENDED_B,
+            UnicodeBlock.IMPERIAL_ARAMAIC,
+            UnicodeBlock.OLD_SOUTH_ARABIAN,
+            UnicodeBlock.AVESTAN,
+            UnicodeBlock.INSCRIPTIONAL_PARTHIAN,
+            UnicodeBlock.INSCRIPTIONAL_PAHLAVI,
+            UnicodeBlock.OLD_TURKIC,
+            UnicodeBlock.RUMI_NUMERAL_SYMBOLS,
+            UnicodeBlock.KAITHI,
+            UnicodeBlock.EGYPTIAN_HIEROGLYPHS,
+            UnicodeBlock.ENCLOSED_ALPHANUMERIC_SUPPLEMENT,
+            UnicodeBlock.ENCLOSED_IDEOGRAPHIC_SUPPLEMENT,
+            UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C,
+
+            // Unicode 6.0.
+            UnicodeBlock.MANDAIC,
+            UnicodeBlock.BATAK,
+            UnicodeBlock.ETHIOPIC_EXTENDED_A,
+            UnicodeBlock.BRAHMI,
+            UnicodeBlock.BAMUM_SUPPLEMENT,
+            UnicodeBlock.KANA_SUPPLEMENT,
+            UnicodeBlock.PLAYING_CARDS,
+            UnicodeBlock.MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS,
+            UnicodeBlock.EMOTICONS,
+            UnicodeBlock.TRANSPORT_AND_MAP_SYMBOLS,
+            UnicodeBlock.ALCHEMICAL_SYMBOLS,
+            UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D,
         };
 
         /**
-         * Retrieves the constant that corresponds to the specified block name.
-         * The block names are defined by the Unicode 4.0.1 specification in the
-         * {@code Blocks-4.0.1.txt} file.
-         * <p>
-         * Block names may be one of the following:
+         * Returns the Unicode block for the given block name, or null if there is no
+         * such block.
+         *
+         * <p>Block names may be one of the following:
          * <ul>
          * <li>Canonical block name, as defined by the Unicode specification;
          * case-insensitive.</li>
          * <li>Canonical block name without any spaces, as defined by the
          * Unicode specification; case-insensitive.</li>
-         * <li>{@code UnicodeBlock} constant identifier. This is determined by
-         * uppercasing the canonical name and replacing all spaces and hyphens
+         * <li>A {@code UnicodeBlock} constant identifier. This is determined by
+         * converting the canonical name to uppercase and replacing all spaces and hyphens
          * with underscores.</li>
          * </ul>
          *
-         * @param blockName
-         *            the name of the block to retrieve.
-         * @return the UnicodeBlock constant corresponding to {@code blockName}.
          * @throws NullPointerException
-         *             if {@code blockName} is {@code null}.
+         *             if {@code blockName == null}.
          * @throws IllegalArgumentException
-         *             if {@code blockName} is not a valid block name.
+         *             if {@code blockName} is not the name of any known block.
          * @since 1.5
          */
         public static UnicodeBlock forName(String blockName) {
@@ -1506,47 +1491,22 @@
             }
             int block = forNameImpl(blockName);
             if (block == -1) {
-                if (blockName.equals("SURROGATES_AREA")) {
-                    return SURROGATES_AREA;
-                } else if(blockName.equalsIgnoreCase("greek")) {
-                    return GREEK;
-                } else if(blockName.equals("COMBINING_MARKS_FOR_SYMBOLS") ||
-                        blockName.equals("Combining Marks for Symbols") ||
-                        blockName.equals("CombiningMarksforSymbols")) {
-                    return COMBINING_MARKS_FOR_SYMBOLS;
-                }
-                throw new IllegalArgumentException("Bad block name: " + blockName);
+                throw new IllegalArgumentException("Unknown block: " + blockName);
             }
             return BLOCKS[block];
         }
 
         /**
-         * Gets the constant for the Unicode block that contains the specified
-         * character.
-         *
-         * @param c
-         *            the character for which to get the {@code UnicodeBlock}
-         *            constant.
-         * @return the {@code UnicodeBlock} constant for the block that contains
-         *         {@code c}, or {@code null} if {@code c} does not belong to
-         *         any defined block.
+         * Returns the Unicode block containing the given code point, or null if the
+         * code point does not belong to any known block.
          */
         public static UnicodeBlock of(char c) {
             return of((int) c);
         }
 
         /**
-         * Gets the constant for the Unicode block that contains the specified
-         * Unicode code point.
-         *
-         * @param codePoint
-         *            the Unicode code point for which to get the
-         *            {@code UnicodeBlock} constant.
-         * @return the {@code UnicodeBlock} constant for the block that contains
-         *         {@code codePoint}, or {@code null} if {@code codePoint} does
-         *         not belong to any defined block.
-         * @throws IllegalArgumentException if {@code codePoint} is not a valid code point.
-         * @since 1.5
+         * Returns the Unicode block containing the given code point, or null if the
+         * code point does not belong to any known block.
          */
         public static UnicodeBlock of(int codePoint) {
             checkValidCodePoint(codePoint);
@@ -1557,7 +1517,7 @@
             return BLOCKS[block];
         }
 
-        private UnicodeBlock(String blockName, int start, int end) {
+        private UnicodeBlock(String blockName) {
             super(blockName);
         }
     }
@@ -1614,7 +1574,6 @@
      * Compares two {@code char} values.
      * @return 0 if lhs = rhs, less than 0 if lhs &lt; rhs, and greater than 0 if lhs &gt; rhs.
      * @since 1.7
-     * @hide 1.7
      */
     public static int compare(char lhs, char rhs) {
         return lhs - rhs;
@@ -1706,9 +1665,8 @@
     }
 
     /**
-     * Tests whether the given character is a high or low surrogate.
+     * Returns true if the given character is a high or low surrogate.
      * @since 1.7
-     * @hide 1.7
      */
     public static boolean isSurrogate(char ch) {
         return ch >= MIN_SURROGATE && ch <= MAX_SURROGATE;
@@ -2433,7 +2391,8 @@
     }
 
     /**
-     * Returns the name of the given code point, or null if the code point is unassigned.
+     * Returns a human-readable name for the given code point,
+     * or null if the code point is unassigned.
      *
      * <p>As a fallback mechanism this method returns strings consisting of the Unicode
      * block name (with underscores replaced by spaces), a single space, and the uppercase
@@ -2447,9 +2406,10 @@
      * <li>{@code Character.getName(0xe000)} returns "PRIVATE USE AREA E000".
      * </ul>
      *
+     * <p>Note that the exact strings returned will vary from release to release.
+     *
      * @throws IllegalArgumentException if {@code codePoint} is not a valid code point.
      * @since 1.7
-     * @hide 1.7
      */
     public static String getName(int codePoint) {
         checkValidCodePoint(codePoint);
@@ -2620,7 +2580,6 @@
      * Returns the high surrogate for the given code point. The result is meaningless if
      * the given code point is not a supplementary character.
      * @since 1.7
-     * @hide 1.7
      */
     public static char highSurrogate(int codePoint) {
         return (char) ((codePoint >> 10) + 0xd7c0);
@@ -2630,20 +2589,25 @@
      * Returns the low surrogate for the given code point. The result is meaningless if
      * the given code point is not a supplementary character.
      * @since 1.7
-     * @hide 1.7
      */
     public static char lowSurrogate(int codePoint) {
         return (char) ((codePoint & 0x3ff) | 0xdc00);
     }
 
     /**
-     * Tests whether the given code point is in the Basic Multilingual Plane (BMP).
+     * Returns true if the given code point is alphabetic. That is,
+     * if it is in any of the Lu, Ll, Lt, Lm, Lo, Nl, or Other_Alphabetic categories.
+     * @since 1.7
+     */
+    public static native boolean isAlphabetic(int codePoint);
+
+    /**
+     * Returns true if the given code point is in the Basic Multilingual Plane (BMP).
      * Such code points can be represented by a single {@code char}.
      * @since 1.7
-     * @hide 1.7
      */
     public static boolean isBmpCodePoint(int codePoint) {
-        return codePoint >= 0 && codePoint <= 0xffff;
+       return codePoint >= Character.MIN_VALUE && codePoint <= Character.MAX_VALUE;
     }
 
     /**
@@ -2720,6 +2684,12 @@
     }
 
     /**
+     * Returns true if the given code point is a CJKV ideographic character.
+     * @since 1.7
+     */
+    public static native boolean isIdeographic(int codePoint);
+
+    /**
      * Indicates whether the specified code point is ignorable in a Java or
      * Unicode identifier.
      *
@@ -2842,7 +2812,7 @@
      *            the character to check.
      * @return {@code true} if {@code c} is a Java letter; {@code false}
      *         otherwise.
-     * @deprecated Use {@link #isJavaIdentifierStart(char)}
+     * @deprecated Use {@link #isJavaIdentifierStart(char)} instead.
      */
     @Deprecated
     public static boolean isJavaLetter(char c) {
@@ -2857,7 +2827,7 @@
      *            the character to check.
      * @return {@code true} if {@code c} is a Java letter or digit;
      *         {@code false} otherwise.
-     * @deprecated Use {@link #isJavaIdentifierPart(char)}
+     * @deprecated Use {@link #isJavaIdentifierPart(char)} instead.
      */
     @Deprecated
     public static boolean isJavaLetterOrDigit(char c) {
@@ -2965,13 +2935,8 @@
     private static native boolean isLowerCaseImpl(int codePoint);
 
     /**
-     * Indicates whether the specified character is a Java space.
-     *
-     * @param c
-     *            the character to check.
-     * @return {@code true} if {@code c} is a Java space; {@code false}
-     *         otherwise.
-     * @deprecated Use {@link #isWhitespace(char)}
+     * Use {@link #isWhitespace(char)} instead.
+     * @deprecated Use {@link #isWhitespace(char)} instead.
      */
     @Deprecated
     public static boolean isSpace(char c) {
@@ -2979,40 +2944,41 @@
     }
 
     /**
-     * Indicates whether the specified character is a Unicode space character.
-     * That is, if it is a member of one of the Unicode categories Space
-     * Separator, Line Separator, or Paragraph Separator.
-     *
-     * @param c
-     *            the character to check.
-     * @return {@code true} if {@code c} is a Unicode space character,
-     *         {@code false} otherwise.
+     * See {@link #isSpaceChar(int)}.
      */
     public static boolean isSpaceChar(char c) {
         return isSpaceChar((int) c);
     }
 
     /**
-     * Indicates whether the specified code point is a Unicode space character.
-     * That is, if it is a member of one of the Unicode categories Space
-     * Separator, Line Separator, or Paragraph Separator.
-     *
-     * @param codePoint
-     *            the code point to check.
-     * @return {@code true} if {@code codePoint} is a Unicode space character,
-     *         {@code false} otherwise.
+     * Returns true if the given code point is a Unicode space character.
+     * The exact set of characters considered as whitespace varies with Unicode version.
+     * Note that non-breaking spaces are considered whitespace.
+     * Note also that line separators are not considered whitespace; see {@link #isWhitespace}
+     * for an alternative.
      */
     public static boolean isSpaceChar(int codePoint) {
-        if (codePoint == 0x20 || codePoint == 0xa0 || codePoint == 0x1680) {
+        // We don't just call into icu4c because of the JNI overhead. Ideally we'd fix that.
+        // SPACE or NO-BREAK SPACE?
+        if (codePoint == 0x20 || codePoint == 0xa0) {
+            return true;
+        }
+        if (codePoint < 0x1000) {
+            return false;
+        }
+        // OGHAM SPACE MARK or MONGOLIAN VOWEL SEPARATOR?
+        if (codePoint == 0x1680 || codePoint == 0x180e) {
             return true;
         }
         if (codePoint < 0x2000) {
             return false;
         }
         if (codePoint <= 0xffff) {
-            return codePoint <= 0x200b || codePoint == 0x2028 || codePoint == 0x2029 ||
-                    codePoint == 0x202f || codePoint == 0x3000;
+            // Other whitespace from General Punctuation...
+            return codePoint <= 0x200a || codePoint == 0x2028 || codePoint == 0x2029 || codePoint == 0x202f || codePoint == 0x205f ||
+                codePoint == 0x3000; // ...or CJK Symbols and Punctuation?
         }
+        // Let icu4c worry about non-BMP code points.
         return isSpaceCharImpl(codePoint);
     }
 
@@ -3134,42 +3100,45 @@
     private static native boolean isUpperCaseImpl(int codePoint);
 
     /**
-     * Indicates whether the specified character is a whitespace character in
-     * Java.
-     *
-     * @param c
-     *            the character to check.
-     * @return {@code true} if the supplied {@code c} is a whitespace character
-     *         in Java; {@code false} otherwise.
+     * See {@link #isWhitespace(int)}.
      */
     public static boolean isWhitespace(char c) {
         return isWhitespace((int) c);
     }
 
     /**
-     * Indicates whether the specified code point is a whitespace character in
-     * Java.
-     *
-     * @param codePoint
-     *            the code point to check.
-     * @return {@code true} if the supplied {@code c} is a whitespace character
-     *         in Java; {@code false} otherwise.
+     * Returns true if the given code point is a Unicode whitespace character.
+     * The exact set of characters considered as whitespace varies with Unicode version.
+     * Note that non-breaking spaces are not considered whitespace.
+     * Note also that line separators are considered whitespace; see {@link #isSpaceChar}
+     * for an alternative.
      */
     public static boolean isWhitespace(int codePoint) {
-        // This is both an optimization and papers over differences between Java and ICU.
-        if ((codePoint >= 0x1c && codePoint <= 0x20) || (codePoint >= 0x9 && codePoint <= 0xd)) {
+        // We don't just call into icu4c because of the JNI overhead. Ideally we'd fix that.
+        // Any ASCII whitespace character?
+        if ((codePoint >= 0x1c && codePoint <= 0x20) || (codePoint >= 0x09 && codePoint <= 0x0d)) {
             return true;
         }
-        if (codePoint == 0x1680) {
+        if (codePoint < 0x1000) {
+            return false;
+        }
+        // OGHAM SPACE MARK or MONGOLIAN VOWEL SEPARATOR?
+        if (codePoint == 0x1680 || codePoint == 0x180e) {
             return true;
         }
-        if (codePoint < 0x2000 || codePoint == 0x2007) {
+        if (codePoint < 0x2000) {
+            return false;
+        }
+        // Exclude General Punctuation's non-breaking spaces (which includes FIGURE SPACE).
+        if (codePoint == 0x2007 || codePoint == 0x202f) {
             return false;
         }
         if (codePoint <= 0xffff) {
-            return codePoint <= 0x200b || codePoint == 0x2028 || codePoint == 0x2029 ||
-                    codePoint == 0x3000;
+            // Other whitespace from General Punctuation...
+            return codePoint <= 0x200a || codePoint == 0x2028 || codePoint == 0x2029 || codePoint == 0x205f ||
+                codePoint == 0x3000; // ...or CJK Symbols and Punctuation?
         }
+        // Let icu4c worry about non-BMP code points.
         return isWhitespaceImpl(codePoint);
     }
 
diff --git a/luni/src/main/java/java/lang/ClassNotFoundException.java b/luni/src/main/java/java/lang/ClassNotFoundException.java
index 2ac3b49..c7ac51d 100644
--- a/luni/src/main/java/java/lang/ClassNotFoundException.java
+++ b/luni/src/main/java/java/lang/ClassNotFoundException.java
@@ -20,7 +20,7 @@
 /**
  * Thrown when a class loader is unable to find a class.
  */
-public class ClassNotFoundException extends Exception {
+public class ClassNotFoundException extends ReflectiveOperationException {
 
     private static final long serialVersionUID = 9176873029745254542L;
 
diff --git a/luni/src/main/java/java/lang/IllegalAccessException.java b/luni/src/main/java/java/lang/IllegalAccessException.java
index 4625395..63fae94 100644
--- a/luni/src/main/java/java/lang/IllegalAccessException.java
+++ b/luni/src/main/java/java/lang/IllegalAccessException.java
@@ -21,7 +21,7 @@
  * Thrown when a program attempts to access a field or method which is not
  * accessible from the location where the reference is made.
  */
-public class IllegalAccessException extends Exception {
+public class IllegalAccessException extends ReflectiveOperationException {
 
     private static final long serialVersionUID = 6616958222490762034L;
 
diff --git a/luni/src/main/java/java/lang/InstantiationException.java b/luni/src/main/java/java/lang/InstantiationException.java
index a5f288b..d08cc75 100644
--- a/luni/src/main/java/java/lang/InstantiationException.java
+++ b/luni/src/main/java/java/lang/InstantiationException.java
@@ -21,7 +21,7 @@
  * Thrown when a program attempts to access a constructor which is not
  * accessible from the location where the reference is made.
  */
-public class InstantiationException extends Exception {
+public class InstantiationException extends ReflectiveOperationException {
     private static final long serialVersionUID = -8441929162975509110L;
 
     /**
diff --git a/luni/src/main/java/java/lang/Integer.java b/luni/src/main/java/java/lang/Integer.java
index 15511a8..fc38b41 100644
--- a/luni/src/main/java/java/lang/Integer.java
+++ b/luni/src/main/java/java/lang/Integer.java
@@ -128,7 +128,6 @@
      * Compares two {@code int} values.
      * @return 0 if lhs = rhs, less than 0 if lhs &lt; rhs, and greater than 0 if lhs &gt; rhs.
      * @since 1.7
-     * @hide 1.7
      */
     public static int compare(int lhs, int rhs) {
         return lhs < rhs ? -1 : (lhs == rhs ? 0 : 1);
diff --git a/luni/src/main/java/java/lang/LinkageError.java b/luni/src/main/java/java/lang/LinkageError.java
index 0bd0a53..07f58f4 100644
--- a/luni/src/main/java/java/lang/LinkageError.java
+++ b/luni/src/main/java/java/lang/LinkageError.java
@@ -49,7 +49,6 @@
     /**
      * Constructs a new {@code LinkageError} with the given detail message and cause.
      * @since 1.7
-     * @hide 1.7
      */
     public LinkageError(String detailMessage, Throwable cause) {
         super(detailMessage, cause);
diff --git a/luni/src/main/java/java/lang/Long.java b/luni/src/main/java/java/lang/Long.java
index 8b592e2..84169af 100644
--- a/luni/src/main/java/java/lang/Long.java
+++ b/luni/src/main/java/java/lang/Long.java
@@ -115,7 +115,6 @@
      * Compares two {@code long} values.
      * @return 0 if lhs = rhs, less than 0 if lhs &lt; rhs, and greater than 0 if lhs &gt; rhs.
      * @since 1.7
-     * @hide 1.7
      */
     public static int compare(long lhs, long rhs) {
         return lhs < rhs ? -1 : (lhs == rhs ? 0 : 1);
diff --git a/luni/src/main/java/java/lang/Math.java b/luni/src/main/java/java/lang/Math.java
index f8d22ed..86df784 100644
--- a/luni/src/main/java/java/lang/Math.java
+++ b/luni/src/main/java/java/lang/Math.java
@@ -54,7 +54,9 @@
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
      */
-    public static native double abs(double d);
+    public static double abs(double d) {
+        return Double.longBitsToDouble(Double.doubleToRawLongBits(d) & 0x7fffffffffffffffL);
+    }
 
     /**
      * Returns the absolute value of the argument.
@@ -67,7 +69,9 @@
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
      */
-    public static native float abs(float f);
+    public static float abs(float f) {
+        return Float.intBitsToFloat(Float.floatToRawIntBits(f) & 0x7fffffff);
+    }
 
     /**
      * Returns the absolute value of the argument.
@@ -75,13 +79,17 @@
      * If the argument is {@code Integer.MIN_VALUE}, {@code Integer.MIN_VALUE}
      * is returned.
      */
-    public static native int abs(int i);
+    public static int abs(int i) {
+        return (i >= 0) ? i : -i;
+    }
 
     /**
      * Returns the absolute value of the argument. If the argument is {@code
      * Long.MIN_VALUE}, {@code Long.MIN_VALUE} is returned.
      */
-    public static native long abs(long l);
+    public static long abs(long l) {
+        return (l >= 0) ? l : -l;
+    }
 
     /**
      * Returns the closest double approximation of the arc cosine of the
@@ -495,7 +503,9 @@
      * Returns the most positive (closest to positive infinity) of the two
      * arguments.
      */
-    public static native int max(int i1, int i2);
+    public static int max(int i1, int i2) {
+        return i1 > i2 ? i1 : i2;
+    }
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
@@ -571,7 +581,9 @@
      * Returns the most negative (closest to negative infinity) of the two
      * arguments.
      */
-    public static native int min(int i1, int i2);
+    public static int min(int i1, int i2) {
+        return i1 < i2 ? i1 : i2;
+    }
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
diff --git a/luni/src/main/java/java/lang/NoSuchFieldException.java b/luni/src/main/java/java/lang/NoSuchFieldException.java
index bea6ecb..9cb88d0 100644
--- a/luni/src/main/java/java/lang/NoSuchFieldException.java
+++ b/luni/src/main/java/java/lang/NoSuchFieldException.java
@@ -21,7 +21,7 @@
  * Thrown when the VM notices that a program tries to reference,
  * on a class or object, a field that does not exist.
  */
-public class NoSuchFieldException extends Exception {
+public class NoSuchFieldException extends ReflectiveOperationException {
 
     private static final long serialVersionUID = -6143714805279938260L;
 
diff --git a/luni/src/main/java/java/lang/NoSuchMethodException.java b/luni/src/main/java/java/lang/NoSuchMethodException.java
index 7cae49b..568547b 100644
--- a/luni/src/main/java/java/lang/NoSuchMethodException.java
+++ b/luni/src/main/java/java/lang/NoSuchMethodException.java
@@ -21,7 +21,7 @@
  * Thrown when the VM notices that a program tries to reference,
  * on a class or object, a method that does not exist.
  */
-public class NoSuchMethodException extends Exception {
+public class NoSuchMethodException extends ReflectiveOperationException {
 
     private static final long serialVersionUID = 5034388446362600923L;
 
diff --git a/luni/src/main/java/java/lang/ReflectiveOperationException.java b/luni/src/main/java/java/lang/ReflectiveOperationException.java
new file mode 100644
index 0000000..835379c
--- /dev/null
+++ b/luni/src/main/java/java/lang/ReflectiveOperationException.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+package java.lang;
+
+import java.lang.reflect.Array;
+
+/**
+ * Superclass of exceptions related to reflection.
+ *
+ * @since 1.7
+ */
+public class ReflectiveOperationException extends Exception {
+  /**
+   * Constructs a new exception with no detail message.
+   */
+  public ReflectiveOperationException() {
+  }
+
+  /**
+   * Constructs a new exception with the given detail message.
+   */
+  public ReflectiveOperationException(String message) {
+    super(message);
+  }
+
+  /**
+   * Constructs a new exception with the given cause.
+   */
+  public ReflectiveOperationException(Throwable cause) {
+    super(cause);
+  }
+
+  /**
+   * Constructs a new exception with the given detail message and cause.
+   */
+  public ReflectiveOperationException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}
diff --git a/luni/src/main/java/java/lang/Runtime.java b/luni/src/main/java/java/lang/Runtime.java
index 5ded981..8538f8a 100644
--- a/luni/src/main/java/java/lang/Runtime.java
+++ b/luni/src/main/java/java/lang/Runtime.java
@@ -47,6 +47,7 @@
 import java.util.StringTokenizer;
 import libcore.io.IoUtils;
 import libcore.io.Libcore;
+import libcore.util.EmptyArray;
 import static libcore.io.OsConstants._SC_NPROCESSORS_CONF;
 
 /**
@@ -66,7 +67,22 @@
     /**
      * Holds the library paths, used for native library lookup.
      */
-    private final String[] mLibPaths;
+    private final String[] mLibPaths = initLibPaths();
+
+    private static String[] initLibPaths() {
+        String javaLibraryPath = System.getProperty("java.library.path");
+        if (javaLibraryPath == null) {
+            return EmptyArray.STRING;
+        }
+        String[] paths = javaLibraryPath.split(":");
+        // Add a '/' to the end of each directory so we don't have to do it every time.
+        for (int i = 0; i < paths.length; ++i) {
+            if (!paths[i].endsWith("/")) {
+                paths[i] += "/";
+            }
+        }
+        return paths;
+    }
 
     /**
      * Holds the list of threads to run when the VM terminates
@@ -93,19 +109,6 @@
      * Prevent this class from being instantiated.
      */
     private Runtime() {
-        String pathList = System.getProperty("java.library.path", ".");
-        String pathSep = System.getProperty("path.separator", ":");
-        String fileSep = System.getProperty("file.separator", "/");
-
-        mLibPaths = pathList.split(pathSep);
-
-        // Add a '/' to the end so we don't have to do the property lookup
-        // and concatenation later.
-        for (int i = 0; i < mLibPaths.length; i++) {
-            if (!mLibPaths[i].endsWith(fileSep)) {
-                mLibPaths[i] += fileSep;
-            }
-        }
     }
 
     /**
@@ -480,7 +483,7 @@
      * @param stream
      *            the input stream to localize.
      * @return the localized input stream.
-     * @deprecated Use {@link InputStreamReader}.
+     * @deprecated Use {@link InputStreamReader} instead.
      */
     @Deprecated
     public InputStream getLocalizedInputStream(InputStream stream) {
@@ -500,7 +503,7 @@
      * @param stream
      *            the output stream to localize.
      * @return the localized output stream.
-     * @deprecated Use {@link OutputStreamWriter}.
+     * @deprecated Use {@link OutputStreamWriter} instead.
      */
     @Deprecated
     public OutputStream getLocalizedOutputStream(OutputStream stream) {
diff --git a/luni/src/main/java/java/lang/SafeVarargs.java b/luni/src/main/java/java/lang/SafeVarargs.java
new file mode 100644
index 0000000..52baa4d
--- /dev/null
+++ b/luni/src/main/java/java/lang/SafeVarargs.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+package java.lang;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Claims to the compiler that the annotation target does nothing potentially unsafe
+ * to its varargs argument.
+ *
+ * @since 1.7
+ */
+@Documented
+@Retention(value=RetentionPolicy.RUNTIME)
+@Target(value={ElementType.CONSTRUCTOR, ElementType.METHOD})
+public @interface SafeVarargs {
+}
diff --git a/luni/src/main/java/java/lang/SecurityManager.java b/luni/src/main/java/java/lang/SecurityManager.java
index 98e92cc..55ade78 100644
--- a/luni/src/main/java/java/lang/SecurityManager.java
+++ b/luni/src/main/java/java/lang/SecurityManager.java
@@ -30,7 +30,7 @@
  */
 public class SecurityManager {
     /**
-     * @deprecated Use {@link #checkPermission}
+     * @deprecated Use {@link #checkPermission} instead.
      */
     @Deprecated
     protected boolean inCheck;
@@ -64,7 +64,7 @@
     public void checkMulticast(InetAddress maddr) { }
 
     /**
-     * @deprecated use {@link #checkMulticast(java.net.InetAddress)}
+     * @deprecated use {@link #checkMulticast(java.net.InetAddress)} instead.
      */
     @Deprecated public void checkMulticast(InetAddress maddr, byte ttl) { }
 
@@ -99,41 +99,41 @@
     public void checkWrite(String file) { }
 
     /**
-     * @deprecated Use {@link #checkPermission}.
+     * @deprecated Use {@link #checkPermission} instead.
      */
     @Deprecated public boolean getInCheck() { return inCheck; }
 
     protected Class[] getClassContext() { return null; }
 
     /**
-     * @deprecated Use {@link #checkPermission}.
+     * @deprecated Use {@link #checkPermission} instead.
      */
     @Deprecated protected ClassLoader currentClassLoader() { return null; }
 
     /**
-     * @deprecated Use {@link #checkPermission}.
+     * @deprecated Use {@link #checkPermission} instead.
      */
     @Deprecated protected int classLoaderDepth() {
         return -1;
     }
 
     /**
-     * @deprecated Use {@link #checkPermission}.
+     * @deprecated Use {@link #checkPermission} instead.
      */
     @Deprecated protected Class<?> currentLoadedClass() { return null; }
 
     /**
-     * @deprecated Use {@link #checkPermission}.
+     * @deprecated Use {@link #checkPermission} instead.
      */
     @Deprecated protected int classDepth(String name) { return -1; }
 
     /**
-     * @deprecated Use {@link #checkPermission}.
+     * @deprecated Use {@link #checkPermission} instead.
      */
     @Deprecated protected boolean inClass(String name) { return false; }
 
     /**
-     * @deprecated Use {@link #checkPermission}
+     * @deprecated Use {@link #checkPermission} instead.
      */
     @Deprecated protected boolean inClassLoader() { return false; }
 
diff --git a/luni/src/main/java/java/lang/Short.java b/luni/src/main/java/java/lang/Short.java
index 1101805..4479c4c 100644
--- a/luni/src/main/java/java/lang/Short.java
+++ b/luni/src/main/java/java/lang/Short.java
@@ -112,9 +112,8 @@
      * Compares two {@code short} values.
      * @return 0 if lhs = rhs, less than 0 if lhs &lt; rhs, and greater than 0 if lhs &gt; rhs.
      * @since 1.7
-     * @hide 1.7
      */
-    public static int compare(long lhs, long rhs) {
+    public static int compare(short lhs, short rhs) {
         return lhs > rhs ? 1 : (lhs < rhs ? -1 : 0);
     }
 
diff --git a/luni/src/main/java/java/lang/System.java b/luni/src/main/java/java/lang/System.java
index 7205ad5..c825118 100644
--- a/luni/src/main/java/java/lang/System.java
+++ b/luni/src/main/java/java/lang/System.java
@@ -51,7 +51,9 @@
 import java.util.Properties;
 import java.util.Set;
 import libcore.icu.ICU;
+import libcore.io.ErrnoException;
 import libcore.io.Libcore;
+import libcore.io.StructPasswd;
 import libcore.io.StructUtsname;
 import libcore.util.ZoneInfoDB;
 
@@ -179,13 +181,10 @@
     public static native long nanoTime();
 
     /**
-     * Causes the VM to stop running and the program to exit. If
-     * {@link #runFinalizersOnExit(boolean)} has been previously invoked with a
+     * Causes the VM to stop running and the program to exit with the given exit status.
+     * If {@link #runFinalizersOnExit(boolean)} has been previously invoked with a
      * {@code true} argument, then all objects will be properly
      * garbage-collected and finalized first.
-     *
-     * @param code
-     *            the return code.
      */
     public static void exit(int code) {
         Runtime.getRuntime().exit(code);
@@ -201,30 +200,18 @@
     }
 
     /**
-     * Returns the value of the environment variable with the given name {@code
-     * var}.
-     *
-     * @param name
-     *            the name of the environment variable.
-     * @return the value of the specified environment variable or {@code null}
-     *         if no variable exists with the given name.
+     * Returns the value of the environment variable with the given name, or null if no such
+     * variable exists.
      */
     public static String getenv(String name) {
-        return getenv(name, null);
-    }
-
-    private static String getenv(String name, String defaultValue) {
         if (name == null) {
             throw new NullPointerException("name == null");
         }
-        String value = Libcore.os.getenv(name);
-        return (value != null) ? value : defaultValue;
+        return Libcore.os.getenv(name);
     }
 
     /**
-     * Returns an unmodifiable map of all available environment variables.
-     *
-     * @return the map representing all environment variables.
+     * Returns an unmodifiable map of all environment variables to their values.
      */
     public static Map<String, String> getenv() {
         Map<String, String> map = new HashMap<String, String>();
@@ -283,10 +270,21 @@
         p.put("java.ext.dirs", "");
         p.put("java.version", "0");
 
-        p.put("java.home", getenv("JAVA_HOME", "/system"));
+        // TODO: does this make any sense? Should we just leave java.home unset?
+        String javaHome = getenv("JAVA_HOME");
+        if (javaHome == null) {
+            javaHome = "/system";
+        }
+        p.put("java.home", javaHome);
 
+        // On Android, each app gets its own temporary directory. This is just a fallback
+        // default, useful only on the host.
         p.put("java.io.tmpdir", "/tmp");
-        p.put("java.library.path", getenv("LD_LIBRARY_PATH"));
+
+        String ldLibraryPath = getenv("LD_LIBRARY_PATH");
+        if (ldLibraryPath != null) {
+            p.put("java.library.path", ldLibraryPath);
+        }
 
         p.put("java.specification.name", "Dalvik Core Library");
         p.put("java.specification.vendor", projectName);
@@ -313,8 +311,13 @@
         p.put("user.language", "en");
         p.put("user.region", "US");
 
-        p.put("user.home", getenv("HOME", ""));
-        p.put("user.name", getenv("USER", ""));
+        try {
+            StructPasswd passwd = Libcore.os.getpwuid(Libcore.os.getuid());
+            p.put("user.home", passwd.pw_dir);
+            p.put("user.name", passwd.pw_name);
+        } catch (ErrnoException exception) {
+            throw new AssertionError(exception);
+        }
 
         StructUtsname info = Libcore.os.uname();
         p.put("os.arch", info.machine);
@@ -325,8 +328,7 @@
         p.put("android.icu.library.version", ICU.getIcuVersion());
         p.put("android.icu.unicode.version", ICU.getUnicodeVersion());
         p.put("android.icu.cldr.version", ICU.getCldrVersion());
-        // TODO: it would be nice to have this but currently it causes circularity.
-        // p.put("android.tzdata.version", ZoneInfoDB.getVersion());
+
         parsePropertyAssignments(p, specialProperties());
 
         // Override built-in properties with settings from the command line.
@@ -370,7 +372,7 @@
      * <tr><td>java.ext.dirs</td>      <td>(Not useful on Android)</td>           <td>Empty</td></tr>
      * <tr><td>java.home</td>          <td>Location of the VM on the file system</td> <td>{@code /system}</td></tr>
      * <tr><td>java.io.tmpdir</td>     <td>See {@link java.io.File#createTempFile}</td> <td>{@code /sdcard}</td></tr>
-     * <tr><td>java.library.path</td>  <td>Search path for JNI libraries</td>     <td>{@code /system/lib}</td></tr>
+     * <tr><td>java.library.path</td>  <td>Search path for JNI libraries</td>     <td>{@code /vendor/lib:/system/lib}</td></tr>
      * <tr><td>java.vendor</td>        <td>Human-readable VM vendor</td>          <td>{@code The Android Project}</td></tr>
      * <tr><td>java.vendor.url</td>    <td>URL for VM vendor's web site</td>      <td>{@code http://www.android.com/}</td></tr>
      * <tr><td>java.version</td>       <td>(Not useful on Android)</td>           <td>{@code 0}</td></tr>
@@ -492,7 +494,6 @@
      * starts. Later changes to the property will not affect the value returned by this
      * method.
      * @since 1.7
-     * @hide 1.7 - fix documentation references to "line.separator" in Formatter.
      */
     public static String lineSeparator() {
         return lineSeparator;
@@ -584,7 +585,7 @@
      *
      * @param flag
      *            the flag determines if finalization on exit is enabled.
-     * @deprecated this method is unsafe.
+     * @deprecated This method is unsafe.
      */
     @SuppressWarnings("deprecation")
     @Deprecated
diff --git a/luni/src/main/java/java/lang/Throwable.java b/luni/src/main/java/java/lang/Throwable.java
index b20b882..fc9180b 100644
--- a/luni/src/main/java/java/lang/Throwable.java
+++ b/luni/src/main/java/java/lang/Throwable.java
@@ -35,8 +35,8 @@
  * circumstances in which the {@code Throwable} was created (basically an error
  * message in most cases), and for saving a stack trace (that is, a record of
  * the call stack at a particular point in time) which can be printed later.
- * <p>
- * A {@code Throwable} can also include a cause, which is a nested {@code
+ *
+ * <p>A {@code Throwable} can also include a cause, which is a nested {@code
  * Throwable} that represents the original problem that led to this {@code
  * Throwable}. It is often used for wrapping various types of errors into a
  * common {@code Throwable} without losing the detailed original error
@@ -81,63 +81,65 @@
      * Constructs a new {@code Throwable} that includes the current stack trace.
      */
     public Throwable() {
+        this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
         fillInStackTrace();
     }
 
     /**
      * Constructs a new {@code Throwable} with the current stack trace and the
-     * specified detail message.
-     *
-     * @param detailMessage
-     *            the detail message for this {@code Throwable}.
+     * given detail message.
      */
     public Throwable(String detailMessage) {
-        this();
         this.detailMessage = detailMessage;
+        this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
+        fillInStackTrace();
     }
 
     /**
      * Constructs a new {@code Throwable} with the current stack trace, the
-     * specified detail message and the specified cause.
-     *
-     * @param detailMessage
-     *            the detail message for this {@code Throwable}.
-     * @param throwable
-     *            the cause of this {@code Throwable}.
+     * given detail message and cause.
      */
-    public Throwable(String detailMessage, Throwable throwable) {
-        this();
+    public Throwable(String detailMessage, Throwable cause) {
         this.detailMessage = detailMessage;
-        cause = throwable;
+        this.cause = cause;
+        this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
+        fillInStackTrace();
     }
 
     /**
      * Constructs a new {@code Throwable} with the current stack trace and the
-     * specified cause.
-     *
-     * @param throwable
-     *            the cause of this {@code Throwable}.
+     * given cause.
      */
-    public Throwable(Throwable throwable) {
-        this();
-        this.detailMessage = throwable == null ? null : throwable.toString();
-        cause = throwable;
+    public Throwable(Throwable cause) {
+        this.detailMessage = cause == null ? null : cause.toString();
+        this.cause = cause;
+        this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
+        fillInStackTrace();
     }
 
     /**
      * Constructs a new {@code Throwable} with the current stack trace, the
      * specified detail message and the specified cause.
      *
-     * @param enableSuppression if false, throwables passed to {@link
-     *     #addSuppressed(Throwable)} will be silently discarded.
+     * @param enableSuppression if false, {@link #addSuppressed(Throwable)} will be a no-op.
+     * @param writableStackTrace if false, {@link #fillInStackTrace} will not be called,
+     * this object's {@code stackTrace} will be null,
+     * calls to {@link #fillInStackTrace} and {@link #setStackTrace} will be no-ops,
+     * and {@link #getStackTrace} will return a zero-length array.
      * @since 1.7
-     * @hide 1.7
      */
-    protected Throwable(String detailMessage, Throwable throwable, boolean enableSuppression) {
-        this(detailMessage, throwable);
+    protected Throwable(String detailMessage, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+        this.detailMessage = detailMessage;
+        this.cause = cause;
         if (!enableSuppression) {
             this.suppressedExceptions = null;
         }
+        if (writableStackTrace) {
+            this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
+            fillInStackTrace();
+        } else {
+            this.stackTrace = null;
+        }
     }
 
     /**
@@ -157,45 +159,41 @@
      * @return this {@code Throwable} instance.
      */
     public Throwable fillInStackTrace() {
-        // Fill in the intermediate representation
+        if (stackTrace == null) {
+            return this; // writableStackTrace was false.
+        }
+        // Fill in the intermediate representation.
         stackState = nativeFillInStackTrace();
-        // Mark the full representation as empty
-        stackTrace = null;
+        // Mark the full representation as in need of update.
+        stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
         return this;
     }
 
     /**
-     * Returns the extra information message which was provided when this
+     * Returns the detail message which was provided when this
      * {@code Throwable} was created. Returns {@code null} if no message was
      * provided at creation time.
-     *
-     * @return this {@code Throwable}'s detail message.
      */
     public String getMessage() {
         return detailMessage;
     }
 
     /**
-     * Returns the extra information message which was provided when this
+     * Returns the detail message which was provided when this
      * {@code Throwable} was created. Returns {@code null} if no message was
      * provided at creation time. Subclasses may override this method to return
      * localized text for the message. Android returns the regular detail message.
-     *
-     * @return this {@code Throwable}'s localized detail message.
      */
     public String getLocalizedMessage() {
         return getMessage();
     }
 
     /**
-     * Returns the array of stack trace elements of this {@code Throwable}. Each
+     * Returns a clone of the array of stack trace elements of this {@code Throwable}. Each
      * {@code StackTraceElement} represents an entry in the call stack. The
      * element at position 0 is the top of the stack, that is, the stack frame
      * where this {@code Throwable} is thrown.
      *
-     * @return a copy of the array of {@code StackTraceElement}s representing
-     *         the call stack. Changes in the array obtained from this call will
-     *         not change the call stack stored in this {@code Throwable}.
      * @see #printStackTrace()
      */
     public StackTraceElement[] getStackTrace() {
@@ -218,6 +216,9 @@
      * @see #printStackTrace()
      */
     public void setStackTrace(StackTraceElement[] trace) {
+        if (stackTrace == null) {
+            return; // writableStackTrace was false.
+        }
         StackTraceElement[] newTrace = trace.clone();
         for (int i = 0; i < newTrace.length; i++) {
             if (newTrace[i] == null) {
@@ -230,7 +231,6 @@
     /**
      * Writes a printable representation of this {@code Throwable}'s stack trace
      * to the {@code System.err} stream.
-     *
      */
     public void printStackTrace() {
         printStackTrace(System.err);
@@ -239,11 +239,6 @@
     /**
      * Counts the number of duplicate stack frames, starting from the
      * end of the stack.
-     *
-     * @param currentStack a stack to compare
-     * @param parentStack a stack to compare
-     *
-     * @return the number of duplicate stack frames.
      */
     private static int countDuplicates(StackTraceElement[] currentStack,
             StackTraceElement[] parentStack) {
@@ -263,25 +258,24 @@
     /**
      * Returns an array of StackTraceElement. Each StackTraceElement
      * represents a entry on the stack.
-     *
-     * @return an array of StackTraceElement representing the stack
      */
     private StackTraceElement[] getInternalStackTrace() {
-        if (stackTrace == null) {
+        if (stackTrace == EmptyArray.STACK_TRACE_ELEMENT) {
             stackTrace = nativeGetStackTrace(stackState);
-            stackState = null; // Clean up intermediate representation
+            stackState = null; // Let go of intermediate representation.
+            return stackTrace;
+        } else if (stackTrace == null) {
+            return EmptyArray.STACK_TRACE_ELEMENT;
+        } else {
+          return stackTrace;
         }
-        return stackTrace;
     }
 
     /**
      * Writes a printable representation of this {@code Throwable}'s stack trace
-     * to the specified print stream. If the {@code Throwable} contains a
+     * to the given print stream. If the {@code Throwable} contains a
      * {@link #getCause() cause}, the method will be invoked recursively for
      * the nested {@code Throwable}.
-     *
-     * @param err
-     *            the stream to write the stack trace on.
      */
     public void printStackTrace(PrintStream err) {
         try {
@@ -392,8 +386,6 @@
     /**
      * Returns the cause of this {@code Throwable}, or {@code null} if there is
      * no cause.
-     *
-     * @return Throwable this {@code Throwable}'s cause.
      */
     public Throwable getCause() {
         if (cause == this) {
@@ -409,7 +401,6 @@
      * @throws IllegalArgumentException if {@code throwable == this}.
      * @throws NullPointerException if {@code throwable == null}.
      * @since 1.7
-     * @hide 1.7
      */
     public final void addSuppressed(Throwable throwable) {
         if (throwable == this) {
@@ -419,9 +410,9 @@
             throw new NullPointerException("throwable == null");
         }
         if (suppressedExceptions != null) {
-            // suppressed exceptions are enabled
+            // Suppressed exceptions are enabled.
             if (suppressedExceptions.isEmpty()) {
-                // ensure we have somewhere to place suppressed exceptions
+                // Ensure we have somewhere to place suppressed exceptions.
                 suppressedExceptions = new ArrayList<Throwable>(1);
             }
             suppressedExceptions.add(throwable);
@@ -432,7 +423,6 @@
      * Returns the throwables suppressed by this.
      *
      * @since 1.7
-     * @hide 1.7
      */
     public final Throwable[] getSuppressed() {
         return (suppressedExceptions != null && !suppressedExceptions.isEmpty())
@@ -441,7 +431,7 @@
     }
 
     private void writeObject(ObjectOutputStream out) throws IOException {
-        // ensure the stackTrace field is initialized
+        // Ensure the stackTrace field is initialized.
         getInternalStackTrace();
         out.defaultWriteObject();
     }
@@ -450,7 +440,7 @@
         in.defaultReadObject();
 
         if (suppressedExceptions != null) {
-            // the deserialized list may be unmodifiable, so just create a mutable copy
+            // The deserialized list may be unmodifiable, so just create a mutable copy.
             suppressedExceptions = new ArrayList<Throwable>(suppressedExceptions);
         }
     }
diff --git a/luni/src/main/java/java/lang/reflect/InvocationTargetException.java b/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
index a87441f..ee75a0e 100644
--- a/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
+++ b/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
@@ -24,7 +24,7 @@
  * @see Method#invoke
  * @see Constructor#newInstance
  */
-public class InvocationTargetException extends Exception {
+public class InvocationTargetException extends ReflectiveOperationException {
 
     private static final long serialVersionUID = 4085088731926701167L;
 
diff --git a/luni/src/main/java/java/lang/reflect/Modifier.java b/luni/src/main/java/java/lang/reflect/Modifier.java
index 225ded1..fdbe3bb 100644
--- a/luni/src/main/java/java/lang/reflect/Modifier.java
+++ b/luni/src/main/java/java/lang/reflect/Modifier.java
@@ -26,20 +26,17 @@
 public class Modifier {
 
     /**
-     * The {@code int} value representing the {@code public}
-     * modifier.
+     * The {@code int} value representing the {@code public} modifier.
      */
     public static final int PUBLIC = 0x1;
 
     /**
-     * The {@code int} value representing the {@code private}
-     * modifier.
+     * The {@code int} value representing the {@code private} modifier.
      */
     public static final int PRIVATE = 0x2;
 
     /**
-     * The {@code int} value representing the {@code protected}
-     * modifier.
+     * The {@code int} value representing the {@code protected} modifier.
      */
     public static final int PROTECTED = 0x4;
 
@@ -54,20 +51,17 @@
     public static final int FINAL = 0x10;
 
     /**
-     * The {@code int} value representing the {@code synchronized}
-     * modifier.
+     * The {@code int} value representing the {@code synchronized} modifier.
      */
     public static final int SYNCHRONIZED = 0x20;
 
     /**
-     * The {@code int} value representing the {@code volatile}
-     * modifier.
+     * The {@code int} value representing the {@code volatile} modifier.
      */
     public static final int VOLATILE = 0x40;
 
     /**
-     * The {@code int} value representing the {@code transient}
-     * modifier.
+     * The {@code int} value representing the {@code transient} modifier.
      */
     public static final int TRANSIENT = 0x80;
 
@@ -77,19 +71,17 @@
     public static final int NATIVE = 0x100;
 
     /**
-     * The {@code int} value representing the {@code interface}
-     * modifier.
+     * The {@code int} value representing the {@code interface} modifier.
      */
     public static final int INTERFACE = 0x200;
 
     /**
-     * The {@code int} value representing the {@code abstract}
-     * modifier.
+     * The {@code int} value representing the {@code abstract} modifier.
      */
     public static final int ABSTRACT = 0x400;
 
     /**
-     * The {@code int} value representing the {@code strict} modifier.
+     * The {@code int} value representing the {@code strictfp} modifier.
      */
     public static final int STRICT = 0x800;
 
@@ -98,13 +90,25 @@
 
     static final int VARARGS = 0x80;
 
-    static final int SYNTHETIC = 0x1000;
+    /**
+     * @hide
+     */
+    public static final int SYNTHETIC = 0x1000;
 
     static final int ANNOTATION = 0x2000;
 
     static final int ENUM = 0x4000;
 
     /**
+     * Miranda methods are fabrications to reserve virtual method
+     * table slots in abstract classes that implement interfaces
+     * without declaring the abstract methods that the interface would
+     * require they implement.
+     * @hide
+     */
+    public static final int MIRANDA = 0x8000;
+
+    /**
      * Constructs a new {@code Modifier} instance.
      */
     public Modifier() {
@@ -113,7 +117,6 @@
     /**
      * Returns a mask of all the modifiers that may be applied to classes.
      * @since 1.7
-     * @hide 1.7
      */
     public static int classModifiers() {
         return PUBLIC | PROTECTED | PRIVATE | ABSTRACT | STATIC | FINAL | STRICT;
@@ -122,7 +125,6 @@
     /**
      * Returns a mask of all the modifiers that may be applied to constructors.
      * @since 1.7
-     * @hide 1.7
      */
     public static int constructorModifiers() {
         return PUBLIC | PROTECTED | PRIVATE;
@@ -131,7 +133,6 @@
     /**
      * Returns a mask of all the modifiers that may be applied to fields.
      * @since 1.7
-     * @hide 1.7
      */
     public static int fieldModifiers() {
         return PUBLIC | PROTECTED | PRIVATE | STATIC | FINAL | TRANSIENT | VOLATILE;
@@ -140,7 +141,6 @@
     /**
      * Returns a mask of all the modifiers that may be applied to interfaces.
      * @since 1.7
-     * @hide 1.7
      */
     public static int interfaceModifiers() {
         return PUBLIC | PROTECTED | PRIVATE | ABSTRACT | STATIC | STRICT;
@@ -149,163 +149,90 @@
     /**
      * Returns a mask of all the modifiers that may be applied to methods.
      * @since 1.7
-     * @hide 1.7
      */
     public static int methodModifiers() {
         return PUBLIC | PROTECTED | PRIVATE | ABSTRACT | STATIC | FINAL | SYNCHRONIZED | NATIVE | STRICT;
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * abstract} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         abstract} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #ABSTRACT}.
      */
     public static boolean isAbstract(int modifiers) {
         return ((modifiers & ABSTRACT) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * final} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         final} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #FINAL}.
      */
     public static boolean isFinal(int modifiers) {
         return ((modifiers & FINAL) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * interface} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         interface} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #INTERFACE}.
      */
     public static boolean isInterface(int modifiers) {
         return ((modifiers & INTERFACE) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * native} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         native} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #NATIVE}.
      */
     public static boolean isNative(int modifiers) {
         return ((modifiers & NATIVE) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * private} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         private} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #PRIVATE}.
      */
     public static boolean isPrivate(int modifiers) {
         return ((modifiers & PRIVATE) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * protected} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         protected} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #PROTECTED}.
      */
     public static boolean isProtected(int modifiers) {
         return ((modifiers & PROTECTED) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * public} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         public} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #PUBLIC}.
      */
     public static boolean isPublic(int modifiers) {
         return ((modifiers & PUBLIC) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * static} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         static} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #STATIC}.
      */
     public static boolean isStatic(int modifiers) {
         return ((modifiers & STATIC) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * strict} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         strict} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #STRICT}.
      */
     public static boolean isStrict(int modifiers) {
         return ((modifiers & STRICT) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * synchronized} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         synchronized} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #SYNCHRONIZED}.
      */
     public static boolean isSynchronized(int modifiers) {
         return ((modifiers & SYNCHRONIZED) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * transient} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         transient} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #TRANSIENT}.
      */
     public static boolean isTransient(int modifiers) {
         return ((modifiers & TRANSIENT) != 0);
     }
 
     /**
-     * Indicates whether or not the specified modifiers contain the {@code
-     * volatile} modifier.
-     *
-     * @param modifiers
-     *            the modifiers to test
-     * @return {@code true} if the specified modifiers contain the {@code
-     *         volatile} modifier, {@code false} otherwise
+     * Returns true if the given modifiers contain {@link #VOLATILE}.
      */
     public static boolean isVolatile(int modifiers) {
         return ((modifiers & VOLATILE) != 0);
@@ -314,17 +241,10 @@
     /**
      * Returns a string containing the string representation of all modifiers
      * present in the specified modifiers. Modifiers appear in the order
-     * specified by the Java Language Specification:
-     *
-     * {@code public private protected abstract static final transient volatile native synchronized interface strict}
-     *
-     * @param modifiers
-     *            the modifiers to print
-     * @return a printable representation of the modifiers
+     * specified by the Java Language Specification.
      */
     public static java.lang.String toString(int modifiers) {
         StringBuilder buf = new StringBuilder();
-
         if (isPublic(modifiers)) {
             buf.append("public ");
         }
diff --git a/luni/src/main/java/java/math/BigDecimal.java b/luni/src/main/java/java/math/BigDecimal.java
index 013809d..03ce8dd 100644
--- a/luni/src/main/java/java/math/BigDecimal.java
+++ b/luni/src/main/java/java/math/BigDecimal.java
@@ -1666,26 +1666,20 @@
     }
 
     /**
-     * Returns a new {@code BigDecimal} whose value is the absolute value of
+     * Returns a {@code BigDecimal} whose value is the absolute value of
      * {@code this}. The scale of the result is the same as the scale of this.
-     *
-     * @return {@code abs(this)}
      */
     public BigDecimal abs() {
         return ((signum() < 0) ? negate() : this);
     }
 
     /**
-     * Returns a new {@code BigDecimal} whose value is the absolute value of
+     * Returns a {@code BigDecimal} whose value is the absolute value of
      * {@code this}. The result is rounded according to the passed context
      * {@code mc}.
-     *
-     * @param mc
-     *            rounding mode and precision for the result of this operation.
-     * @return {@code abs(this)}
      */
     public BigDecimal abs(MathContext mc) {
-        BigDecimal result = abs();
+        BigDecimal result = (signum() < 0) ? negate() : new BigDecimal(getUnscaledValue(), scale);
         result.inplaceRound(mc);
         return result;
     }
diff --git a/luni/src/main/java/java/math/BigInt.java b/luni/src/main/java/java/math/BigInt.java
index 614dbb4..e327a6e 100644
--- a/luni/src/main/java/java/math/BigInt.java
+++ b/luni/src/main/java/java/math/BigInt.java
@@ -24,7 +24,7 @@
 final class BigInt {
 
     /* Fields used for the internal representation. */
-    transient int bignum = 0;
+    transient long bignum = 0;
 
     @Override protected void finalize() throws Throwable {
         try {
@@ -42,53 +42,19 @@
         return this.decString();
     }
 
-    int getNativeBIGNUM() {
+    long getNativeBIGNUM() {
         return this.bignum;
     }
 
-    static int consumeErrors(StringBuilder sb) {
-        int cnt = 0;
-        int e, reason;
-        while ((e = NativeBN.ERR_get_error()) != 0) {
-            reason = e & 255;
-            if (reason == 103) {
-                throw new ArithmeticException("BigInteger division by zero");
-            }
-            if (reason == 108) {
-                throw new ArithmeticException("BigInteger not invertible");
-            }
-            if (reason == 65) {
-                throw new OutOfMemoryError();
-            }
-            sb.append(e).append(": ");
-            String s = NativeBN.ERR_error_string(e);
-            sb.append(s);
-            cnt++;
-        }
-        return cnt;
-    }
-
-    private static void Check(boolean success) {
-        if (!success) {
-            StringBuilder sb = new StringBuilder("(openssl)ERR: ");
-            int cnt = consumeErrors(sb);
-            if (cnt > 0)
-                throw new ArithmeticException(sb.toString());
-        }
-    }
-
-
     private void makeValid() {
         if (this.bignum == 0) {
             this.bignum = NativeBN.BN_new();
-            Check(this.bignum != 0);
         }
     }
 
     private static BigInt newBigInt() {
         BigInt bi = new BigInt();
         bi.bignum = NativeBN.BN_new();
-        Check(bi.bignum != 0);
         return bi;
     }
 
@@ -100,7 +66,7 @@
 
     void putCopy(BigInt from) {
         this.makeValid();
-        Check(NativeBN.BN_copy(this.bignum, from.bignum));
+        NativeBN.BN_copy(this.bignum, from.bignum);
     }
 
     BigInt copy() {
@@ -112,12 +78,12 @@
 
     void putLongInt(long val) {
         this.makeValid();
-        Check(NativeBN.putLongInt(this.bignum, val));
+        NativeBN.putLongInt(this.bignum, val);
     }
 
     void putULongInt(long val, boolean neg) {
         this.makeValid();
-        Check(NativeBN.putULongInt(this.bignum, val, neg));
+        NativeBN.putULongInt(this.bignum, val, neg);
     }
 
     private NumberFormatException invalidBigInteger(String s) {
@@ -128,7 +94,6 @@
         String s = checkString(original, 10);
         this.makeValid();
         int usedLen = NativeBN.BN_dec2bn(this.bignum, s);
-        Check((usedLen > 0));
         if (usedLen < s.length()) {
             throw invalidBigInteger(original);
         }
@@ -138,7 +103,6 @@
         String s = checkString(original, 16);
         this.makeValid();
         int usedLen = NativeBN.BN_hex2bn(this.bignum, s);
-        Check((usedLen > 0));
         if (usedLen < s.length()) {
             throw invalidBigInteger(original);
         }
@@ -205,17 +169,17 @@
 
     void putBigEndian(byte[] a, boolean neg) {
         this.makeValid();
-        Check(NativeBN.BN_bin2bn(a, a.length, neg, this.bignum));
+        NativeBN.BN_bin2bn(a, a.length, neg, this.bignum);
     }
 
     void putLittleEndianInts(int[] a, boolean neg) {
         this.makeValid();
-        Check(NativeBN.litEndInts2bn(a, a.length, neg, this.bignum));
+        NativeBN.litEndInts2bn(a, a.length, neg, this.bignum);
     }
 
     void putBigEndianTwosComplement(byte[] a) {
         this.makeValid();
-        Check(NativeBN.twosComp2bn(a, a.length, this.bignum));
+        NativeBN.twosComp2bn(a, a.length, this.bignum);
     }
 
 
@@ -267,61 +231,59 @@
     // n > 0: shift left (multiply)
     static BigInt shift(BigInt a, int n) {
         BigInt r = newBigInt();
-        Check(NativeBN.BN_shift(r.bignum, a.bignum, n));
+        NativeBN.BN_shift(r.bignum, a.bignum, n);
         return r;
     }
 
     void shift(int n) {
-        Check(NativeBN.BN_shift(this.bignum, this.bignum, n));
+        NativeBN.BN_shift(this.bignum, this.bignum, n);
     }
 
     void addPositiveInt(int w) {
-        Check(NativeBN.BN_add_word(this.bignum, w));
+        NativeBN.BN_add_word(this.bignum, w);
     }
 
     void multiplyByPositiveInt(int w) {
-        Check(NativeBN.BN_mul_word(this.bignum, w));
+        NativeBN.BN_mul_word(this.bignum, w);
     }
 
     static int remainderByPositiveInt(BigInt a, int w) {
-        int rem = NativeBN.BN_mod_word(a.bignum, w);
-        Check(rem != -1);
-        return rem;
+        return NativeBN.BN_mod_word(a.bignum, w);
     }
 
     static BigInt addition(BigInt a, BigInt b) {
         BigInt r = newBigInt();
-        Check(NativeBN.BN_add(r.bignum, a.bignum, b.bignum));
+        NativeBN.BN_add(r.bignum, a.bignum, b.bignum);
         return r;
     }
 
     void add(BigInt a) {
-        Check(NativeBN.BN_add(this.bignum, this.bignum, a.bignum));
+        NativeBN.BN_add(this.bignum, this.bignum, a.bignum);
     }
 
     static BigInt subtraction(BigInt a, BigInt b) {
         BigInt r = newBigInt();
-        Check(NativeBN.BN_sub(r.bignum, a.bignum, b.bignum));
+        NativeBN.BN_sub(r.bignum, a.bignum, b.bignum);
         return r;
     }
 
 
     static BigInt gcd(BigInt a, BigInt b) {
         BigInt r = newBigInt();
-        Check(NativeBN.BN_gcd(r.bignum, a.bignum, b.bignum));
+        NativeBN.BN_gcd(r.bignum, a.bignum, b.bignum);
         return r;
     }
 
     static BigInt product(BigInt a, BigInt b) {
         BigInt r = newBigInt();
-        Check(NativeBN.BN_mul(r.bignum, a.bignum, b.bignum));
+        NativeBN.BN_mul(r.bignum, a.bignum, b.bignum);
         return r;
     }
 
     static BigInt bigExp(BigInt a, BigInt p) {
         // Sign of p is ignored!
         BigInt r = newBigInt();
-        Check(NativeBN.BN_exp(r.bignum, a.bignum, p.bignum));
+        NativeBN.BN_exp(r.bignum, a.bignum, p.bignum);
         return r;
     }
 
@@ -335,9 +297,8 @@
         // int BN_sqr(BIGNUM *r, const BIGNUM *a,BN_CTX *ctx);
     }
 
-    static void division(BigInt dividend, BigInt divisor,
-            BigInt quotient, BigInt remainder) {
-        int quot, rem;
+    static void division(BigInt dividend, BigInt divisor, BigInt quotient, BigInt remainder) {
+        long quot, rem;
         if (quotient != null) {
             quotient.makeValid();
             quot = quotient.bignum;
@@ -350,37 +311,34 @@
         } else {
             rem = 0;
         }
-        Check(NativeBN.BN_div(quot, rem, dividend.bignum, divisor.bignum));
+        NativeBN.BN_div(quot, rem, dividend.bignum, divisor.bignum);
     }
 
     static BigInt modulus(BigInt a, BigInt m) {
         // Sign of p is ignored! ?
         BigInt r = newBigInt();
-        Check(NativeBN.BN_nnmod(r.bignum, a.bignum, m.bignum));
+        NativeBN.BN_nnmod(r.bignum, a.bignum, m.bignum);
         return r;
     }
 
     static BigInt modExp(BigInt a, BigInt p, BigInt m) {
         // Sign of p is ignored!
         BigInt r = newBigInt();
-        Check(NativeBN.BN_mod_exp(r.bignum, a.bignum, p.bignum, m.bignum));
-
-        // OPTIONAL:
-        // int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+        NativeBN.BN_mod_exp(r.bignum, a.bignum, p.bignum, m.bignum);
         return r;
     }
 
 
     static BigInt modInverse(BigInt a, BigInt m) {
         BigInt r = newBigInt();
-        Check(NativeBN.BN_mod_inverse(r.bignum, a.bignum, m.bignum));
+        NativeBN.BN_mod_inverse(r.bignum, a.bignum, m.bignum);
         return r;
     }
 
 
     static BigInt generatePrimeDefault(int bitLength) {
         BigInt r = newBigInt();
-        Check(NativeBN.BN_generate_prime_ex(r.bignum, bitLength, false, 0, 0, 0));
+        NativeBN.BN_generate_prime_ex(r.bignum, bitLength, false, 0, 0, 0);
         return r;
     }
 
diff --git a/luni/src/main/java/java/math/BigInteger.java b/luni/src/main/java/java/math/BigInteger.java
index 90bf0f6..9470b89 100644
--- a/luni/src/main/java/java/math/BigInteger.java
+++ b/luni/src/main/java/java/math/BigInteger.java
@@ -137,7 +137,7 @@
             for (int i = 0; i < numberLength; i++) {
                 digits[i] = random.nextInt();
             }
-            // Using only the necessary bits
+            // Clear any extra bits.
             digits[numberLength - 1] >>>= (-numBits) & 31;
             setJavaRepresentation(sign, numberLength, digits);
         }
@@ -147,12 +147,12 @@
     /**
      * Constructs a random {@code BigInteger} instance in the range {@code [0,
      * pow(2, bitLength)-1]} which is probably prime. The probability that the
-     * returned {@code BigInteger} is prime is beyond
-     * {@code 1 - 1/pow(2, certainty)}.
+     * returned {@code BigInteger} is prime is greater than
+     * {@code 1 - 1/2<sup>certainty</sup>)}.
      *
-     * <p><b>Implementation Note:</b> the {@code Random} argument is ignored.
-     * This implementation uses OpenSSL's {@code bn_rand} as a source of
-     * cryptographically strong pseudo-random numbers.
+     * <p><b>Note:</b> the {@code Random} argument is ignored if
+     * {@code bitLength >= 16}, where this implementation will use OpenSSL's
+     * {@code BN_generate_prime_ex} as a source of cryptographically strong pseudo-random numbers.
      *
      * @param bitLength length of the new {@code BigInteger} in bits.
      * @param certainty tolerated primality uncertainty.
@@ -160,11 +160,45 @@
      * @see <a href="http://www.openssl.org/docs/crypto/BN_rand.html">
      *      Specification of random generator used from OpenSSL library</a>
      */
-    public BigInteger(int bitLength, int certainty, Random unused) {
+    public BigInteger(int bitLength, int certainty, Random random) {
         if (bitLength < 2) {
             throw new ArithmeticException("bitLength < 2: " + bitLength);
         }
-        setBigInt(BigInt.generatePrimeDefault(bitLength));
+        if (bitLength < 16) {
+            // We have to generate short primes ourselves, because OpenSSL bottoms out at 16 bits.
+            int candidate;
+            do {
+                candidate = random.nextInt() & ((1 << bitLength) - 1);
+                candidate |= (1 << (bitLength - 1)); // Set top bit.
+                if (bitLength > 2) {
+                    candidate |= 1; // Any prime longer than 2 bits must have the bottom bit set.
+                }
+            } while (!isSmallPrime(candidate));
+            BigInt prime = new BigInt();
+            prime.putULongInt(candidate, false);
+            setBigInt(prime);
+        } else {
+            // We need a loop here to work around an OpenSSL bug; http://b/8588028.
+            do {
+                setBigInt(BigInt.generatePrimeDefault(bitLength));
+            } while (bitLength() != bitLength);
+        }
+    }
+
+    private static boolean isSmallPrime(int x) {
+        if (x == 2) {
+            return true;
+        }
+        if ((x % 2) == 0) {
+            return false;
+        }
+        final int max = (int) Math.sqrt(x);
+        for (int i = 3; i <= max; i += 2) {
+            if ((x % i) == 0) {
+                return false;
+            }
+        }
+        return true;
     }
 
     /**
@@ -940,26 +974,27 @@
 
     /**
      * Returns a {@code BigInteger} whose value is {@code
-     * pow(this, exponent) mod m}. The modulus {@code m} must be positive. The
-     * result is guaranteed to be in the interval {@code [0, m)} (0 inclusive,
-     * m exclusive). If the exponent is negative, then {@code
-     * pow(this.modInverse(m), -exponent) mod m} is computed. The inverse of
-     * this only exists if {@code this} is relatively prime to m, otherwise an
-     * exception is thrown.
+     * pow(this, exponent) mod modulus}. The modulus must be positive. The
+     * result is guaranteed to be in the interval {@code [0, modulus)}.
+     * If the exponent is negative, then
+     * {@code pow(this.modInverse(modulus), -exponent) mod modulus} is computed.
+     * The inverse of this only exists if {@code this} is relatively prime to the modulus,
+     * otherwise an exception is thrown.
      *
-     * @param exponent the exponent.
-     * @param m the modulus.
-     * @throws NullPointerException if {@code m == null} or {@code exponent ==
-     *     null}.
-     * @throws ArithmeticException if {@code m < 0} or if {@code exponent<0} and
-     *     this is not relatively prime to {@code m}.
+     * @throws NullPointerException if {@code modulus == null} or {@code exponent == null}.
+     * @throws ArithmeticException if {@code modulus < 0} or if {@code exponent < 0} and
+     *     not relatively prime to {@code modulus}.
      */
-    public BigInteger modPow(BigInteger exponent, BigInteger m) {
-        if (m.signum() <= 0) {
-            throw new ArithmeticException("m.signum() <= 0");
+    public BigInteger modPow(BigInteger exponent, BigInteger modulus) {
+        if (modulus.signum() <= 0) {
+            throw new ArithmeticException("modulus.signum() <= 0");
         }
-        BigInteger base = exponent.signum() < 0 ? modInverse(m) : this;
-        return new BigInteger(BigInt.modExp(base.getBigInt(), exponent.getBigInt(), m.getBigInt()));
+        int exponentSignum = exponent.signum();
+        if (exponentSignum == 0) { // OpenSSL gets this case wrong; http://b/8574367.
+            return ONE.mod(modulus);
+        }
+        BigInteger base = exponentSignum < 0 ? modInverse(modulus) : this;
+        return new BigInteger(BigInt.modExp(base.getBigInt(), exponent.getBigInt(), modulus.getBigInt()));
     }
 
     /**
@@ -983,8 +1018,8 @@
 
     /**
      * Tests whether this {@code BigInteger} is probably prime. If {@code true}
-     * is returned, then this is prime with a probability beyond
-     * {@code 1 - 1/pow(2, certainty)}. If {@code false} is returned, then this
+     * is returned, then this is prime with a probability greater than
+     * {@code 1 - 1/2<sup>certainty</sup>)}. If {@code false} is returned, then this
      * is definitely composite. If the argument {@code certainty} <= 0, then
      * this method returns true.
      *
@@ -1002,7 +1037,7 @@
     /**
      * Returns the smallest integer x > {@code this} which is probably prime as
      * a {@code BigInteger} instance. The probability that the returned {@code
-     * BigInteger} is prime is beyond {@code 1 - 1/pow(2, 80)}.
+     * BigInteger} is prime is greater than {@code 1 - 1/2<sup>100</sup>}.
      *
      * @return smallest integer > {@code this} which is probably prime.
      * @throws ArithmeticException if {@code this < 0}.
@@ -1017,17 +1052,14 @@
     /**
      * Returns a random positive {@code BigInteger} instance in the range {@code
      * [0, pow(2, bitLength)-1]} which is probably prime. The probability that
-     * the returned {@code BigInteger} is prime is beyond {@code
-     * 1 - 1/pow(2, 80)}.
-     *
-     * <p><b>Implementation Note:</b> Currently {@code random} is ignored.
+     * the returned {@code BigInteger} is prime is greater than {@code 1 - 1/2<sup>100</sup>)}.
      *
      * @param bitLength length of the new {@code BigInteger} in bits.
      * @return probably prime random {@code BigInteger} instance.
      * @throws IllegalArgumentException if {@code bitLength < 2}.
      */
-    public static BigInteger probablePrime(int bitLength, Random unused) {
-        return new BigInteger(bitLength, 100, unused);
+    public static BigInteger probablePrime(int bitLength, Random random) {
+        return new BigInteger(bitLength, 100, random);
     }
 
     /* Private Methods */
@@ -1035,8 +1067,6 @@
     /**
      * Returns the two's complement representation of this BigInteger in a byte
      * array.
-     *
-     * @return two's complement representation of {@code this}
      */
     private byte[] twosComplement() {
         prepareJavaRepresentation();
diff --git a/luni/src/main/java/java/math/NativeBN.java b/luni/src/main/java/java/math/NativeBN.java
index 95bb2a2..513dafd 100644
--- a/luni/src/main/java/java/math/NativeBN.java
+++ b/luni/src/main/java/java/math/NativeBN.java
@@ -18,148 +18,113 @@
 
 final class NativeBN {
 
-    public static native int ERR_get_error();
-    // unsigned long ERR_get_error(void);
-
-    public static native String ERR_error_string(int e);
-    // char *ERR_error_string(unsigned long e, char *buf);
-
-    public static native int BN_new();
+    public static native long BN_new();
     // BIGNUM *BN_new(void);
 
-    public static native void BN_free(int a);
+    public static native void BN_free(long a);
     // void BN_free(BIGNUM *a);
 
-    public static native int BN_cmp(int a, int b);
+    public static native int BN_cmp(long a, long b);
     // int BN_cmp(const BIGNUM *a, const BIGNUM *b);
 
-    public static native boolean BN_copy(int to, int from);
-    // Returns boolean success AND NOT result BIGNUM handle!
+    public static native void BN_copy(long to, long from);
     // BIGNUM *BN_copy(BIGNUM *to, const BIGNUM *from);
-//    public static native int BN_dup(int from);
-    // BIGNUM *BN_dup(const BIGNUM *a);
 
+    public static native void putLongInt(long a, long dw);
+    public static native void putULongInt(long a, long dw, boolean neg);
 
-    public static native boolean putLongInt(int a, long dw);
-
-    public static native boolean putULongInt(int a, long dw, boolean neg);
-
-    public static native int BN_dec2bn(int a, String str);
+    public static native int BN_dec2bn(long a, String str);
     // int BN_dec2bn(BIGNUM **a, const char *str);
 
-    public static native int BN_hex2bn(int a, String str);
+    public static native int BN_hex2bn(long a, String str);
     // int BN_hex2bn(BIGNUM **a, const char *str);
 
-    public static native boolean BN_bin2bn(byte[] s, int len, boolean neg, int ret);
-    // Returns boolean success AND NOT result BIGNUM handle!
+    public static native void BN_bin2bn(byte[] s, int len, boolean neg, long ret);
     // BIGNUM * BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
     // BN-Docu: s is taken as unsigned big endian;
     // Additional parameter: neg.
 
-    public static native boolean litEndInts2bn(int[] ints, int len, boolean neg, int ret);
+    public static native void litEndInts2bn(int[] ints, int len, boolean neg, long ret);
 
-    public static native boolean twosComp2bn(byte[] s, int len, int ret);
+    public static native void twosComp2bn(byte[] s, int len, long ret);
 
 
-    public static native long longInt(int a);
+    public static native long longInt(long a);
     // unsigned long BN_get_word(BIGNUM *a);
 
-    public static native String BN_bn2dec(int a);
+    public static native String BN_bn2dec(long a);
     // char * BN_bn2dec(const BIGNUM *a);
 
-    public static native String BN_bn2hex(int a);
+    public static native String BN_bn2hex(long a);
     // char * BN_bn2hex(const BIGNUM *a);
 
-    public static native byte[] BN_bn2bin(int a);
+    public static native byte[] BN_bn2bin(long a);
     // Returns result byte[] AND NOT length.
     // int BN_bn2bin(const BIGNUM *a, unsigned char *to);
 
-    public static native int[] bn2litEndInts(int a);
+    public static native int[] bn2litEndInts(long a);
 
-    public static native int sign(int a);
+    public static native int sign(long a);
     // Returns -1, 0, 1 AND NOT boolean.
     // #define BN_is_negative(a) ((a)->neg != 0)
 
-    public static native void BN_set_negative(int b, int n);
+    public static native void BN_set_negative(long b, int n);
     // void BN_set_negative(BIGNUM *b, int n);
 
-    public static native int bitLength(int a);
+    public static native int bitLength(long a);
 
-    public static native boolean BN_is_bit_set(int a, int n);
+    public static native boolean BN_is_bit_set(long a, int n);
     // int BN_is_bit_set(const BIGNUM *a, int n);
 
-    public static native boolean modifyBit(int a, int n, int op);
-    // Returns boolean success.
-    // op: 0 = reset; 1 = set; -1 = flip
-    // uses BN_set_bit(), BN_clear_bit() and BN_is_bit_set()
-
-    public static native boolean BN_shift(int r, int a, int n);
+    public static native void BN_shift(long r, long a, int n);
     // int BN_shift(BIGNUM *r, const BIGNUM *a, int n);
 
-    public static native boolean BN_add_word(int a, int w);
+    public static native void BN_add_word(long a, int w);
     // ATTENTION: w is treated as unsigned.
     // int BN_add_word(BIGNUM *a, BN_ULONG w);
 
-    public static native boolean BN_sub_word(int a, int w);
-    // ATTENTION: w is treated as unsigned.
-    // int BN_sub_word(BIGNUM *a, BN_ULONG w);
-
-    public static native boolean BN_mul_word(int a, int w);
+    public static native void BN_mul_word(long a, int w);
     // ATTENTION: w is treated as unsigned.
     // int BN_mul_word(BIGNUM *a, BN_ULONG w);
 
-    public static native int BN_div_word(int a, int w);
-    // ATTENTION: w is treated as unsigned.
-    // BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
-
-    public static native int BN_mod_word(int a, int w);
+    public static native int BN_mod_word(long a, int w);
     // ATTENTION: w is treated as unsigned.
     // BN_ULONG BN_mod_word(BIGNUM *a, BN_ULONG w);
 
-    public static native boolean BN_add(int r, int a, int b);
+    public static native void BN_add(long r, long a, long b);
     // int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
 
-    public static native boolean BN_sub(int r, int a, int b);
+    public static native void BN_sub(long r, long a, long b);
     // int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
 
-    public static native boolean BN_gcd(int r, int a, int b);
+    public static native void BN_gcd(long r, long a, long b);
     // int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
 
-    public static native boolean BN_mul(int r, int a, int b);
+    public static native void BN_mul(long r, long a, long b);
     // int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
 
-    public static native boolean BN_exp(int r, int a, int p);
+    public static native void BN_exp(long r, long a, long p);
     // int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
 
-    // OPTIONAL:
-//    public static native int BN_sqr(BigInteger r, BigInteger a, BN_CTX ctx);
-    // int BN_sqr(BIGNUM *r, const BIGNUM *a,BN_CTX *ctx);
-
-    public static native boolean BN_div(int dv, int rem, int m, int d);
+    public static native void BN_div(long dv, long rem, long m, long d);
     // int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
 
-    public static native boolean BN_nnmod(int r, int a, int m);
+    public static native void BN_nnmod(long r, long a, long m);
     // int BN_nnmod(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
 
-    public static native boolean BN_mod_exp(int r, int a, int p, int m);
+    public static native void BN_mod_exp(long r, long a, long p, long m);
     // int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx);
 
-    // OPTIONAL:
-//    public static native boolean BN_mod_sqr(BigInteger r, BigInteger a, BigInteger m, BN_CTX ctx);
-    // int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
-
-
-    public static native boolean BN_mod_inverse(int ret, int a, int n);
-    // Returns boolean success AND NOT result BIGNUM handle!
+    public static native void BN_mod_inverse(long ret, long a, long n);
     // BIGNUM * BN_mod_inverse(BIGNUM *ret, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
 
 
-    public static native boolean BN_generate_prime_ex(int ret, int bits, boolean safe,
-            int add, int rem, int cb);
+    public static native void BN_generate_prime_ex(long ret, int bits, boolean safe,
+                                                   long add, long rem, long cb);
     // int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
     //         const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb);
 
-    public static native boolean BN_is_prime_ex(int p, int nchecks, int cb);
+    public static native boolean BN_is_prime_ex(long p, int nchecks, long cb);
     // int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb);
 
 }
diff --git a/luni/src/main/java/java/net/DatagramSocket.java b/luni/src/main/java/java/net/DatagramSocket.java
index 790ebc9..49f141a 100644
--- a/luni/src/main/java/java/net/DatagramSocket.java
+++ b/luni/src/main/java/java/net/DatagramSocket.java
@@ -17,10 +17,12 @@
 
 package java.net;
 
+import java.io.Closeable;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.nio.channels.DatagramChannel;
 import libcore.io.ErrnoException;
+import libcore.io.IoBridge;
 import libcore.io.Libcore;
 import static libcore.io.OsConstants.*;
 
@@ -32,7 +34,7 @@
  * @see DatagramPacket
  * @see DatagramSocketImplFactory
  */
-public class DatagramSocket {
+public class DatagramSocket implements Closeable {
 
     DatagramSocketImpl impl;
 
@@ -150,20 +152,15 @@
     }
 
     /**
-     * Gets the {@code InetAddress} instance representing the bound local
-     * address of this UDP datagram socket.
-     *
-     * @return the local address to which this socket is bound to or {@code
-     *         null} if this socket is closed.
+     * Returns the local address to which this socket is bound,
+     * or {@code null} if this socket is closed.
      */
     public InetAddress getLocalAddress() {
-        if (isClosed()) {
+        try {
+            return IoBridge.getSocketLocalAddress(impl.fd);
+        } catch (SocketException ex) {
             return null;
         }
-        if (!isBound()) {
-            return Inet4Address.ANY;
-        }
-        return impl.getLocalAddress();
     }
 
     /**
diff --git a/luni/src/main/java/java/net/DatagramSocketImpl.java b/luni/src/main/java/java/net/DatagramSocketImpl.java
index 6e706c3..097eb17 100644
--- a/luni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/luni/src/main/java/java/net/DatagramSocketImpl.java
@@ -19,7 +19,6 @@
 
 import java.io.FileDescriptor;
 import java.io.IOException;
-import libcore.io.IoBridge;
 
 /**
  * The abstract superclass for datagram and multicast socket implementations.
@@ -82,13 +81,6 @@
     }
 
     /**
-     * Returns the local address to which the socket is bound.
-     */
-    InetAddress getLocalAddress() {
-        return IoBridge.getSocketLocalAddress(fd);
-    }
-
-    /**
      * Returns the local port to which this socket is bound.
      */
     protected int getLocalPort() {
@@ -102,7 +94,7 @@
      * @throws IOException
      *             if an error occurs while getting the time-to-live option
      *             value.
-     * @deprecated Replaced by {@link #getTimeToLive}
+     * @deprecated Use {@link #getTimeToLive} instead.
      * @see #getTimeToLive()
      */
     @Deprecated
@@ -233,7 +225,7 @@
      *            &lt;= 255.
      * @throws IOException
      *             if an error occurs while setting the option.
-     * @deprecated Replaced by {@link #setTimeToLive}
+     * @deprecated Use {@link #setTimeToLive} instead.
      * @see #setTimeToLive(int)
      */
     @Deprecated
diff --git a/luni/src/main/java/java/net/ExtendedResponseCache.java b/luni/src/main/java/java/net/ExtendedResponseCache.java
deleted file mode 100644
index a70e734..0000000
--- a/luni/src/main/java/java/net/ExtendedResponseCache.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.net;
-
-/**
- * A response cache that supports statistics tracking and updating stored
- * responses. Implementations of {@link ResponseCache} should implement this
- * interface to receive additional support from the HTTP engine.
- *
- * @hide
- */
-public interface ExtendedResponseCache {
-
-    /*
-     * This hidden interface is defined in a non-hidden package (java.net) so
-     * its @hide tag will be parsed by Doclava. This hides this interface from
-     * implementing classes' documentation.
-     */
-
-    /**
-     * Track an HTTP response being satisfied by {@code source}.
-     * @hide
-     */
-    void trackResponse(ResponseSource source);
-
-    /**
-     * Track an conditional GET that was satisfied by this cache.
-     * @hide
-     */
-    void trackConditionalCacheHit();
-
-    /**
-     * Updates stored HTTP headers using a hit on a conditional GET.
-     * @hide
-     */
-    void update(CacheResponse conditionalCacheHit, HttpURLConnection httpConnection);
-}
diff --git a/luni/src/main/java/java/net/HttpURLConnection.java b/luni/src/main/java/java/net/HttpURLConnection.java
index 2023887..d6b2435 100644
--- a/luni/src/main/java/java/net/HttpURLConnection.java
+++ b/luni/src/main/java/java/net/HttpURLConnection.java
@@ -20,7 +20,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Arrays;
-import libcore.net.http.HttpEngine;
 
 /**
  * An {@link URLConnection} for HTTP (<a
@@ -257,19 +256,20 @@
  * request/response pair. Instances of this class are not thread safe.
  */
 public abstract class HttpURLConnection extends URLConnection {
+    private static final int DEFAULT_CHUNK_LENGTH = 1024;
 
     /**
      * The subset of HTTP methods that the user may select via {@link
      * #setRequestMethod(String)}.
      */
     private static final String[] PERMITTED_USER_METHODS = {
-            HttpEngine.OPTIONS,
-            HttpEngine.GET,
-            HttpEngine.HEAD,
-            HttpEngine.POST,
-            HttpEngine.PUT,
-            HttpEngine.DELETE,
-            HttpEngine.TRACE
+            "OPTIONS",
+            "GET",
+            "HEAD",
+            "POST",
+            "PUT",
+            "DELETE",
+            "TRACE"
             // Note: we don't allow users to specify "CONNECT"
     };
 
@@ -277,7 +277,7 @@
      * The HTTP request method of this {@code HttpURLConnection}. The default
      * value is {@code "GET"}.
      */
-    protected String method = HttpEngine.GET;
+    protected String method = "GET";
 
     /**
      * The status code of the response obtained from the HTTP request. The
@@ -312,12 +312,20 @@
     protected int chunkLength = -1;
 
     /**
-     * If using HTTP fixed-length streaming mode this parameter defines the
-     * fixed length of content. Default value is {@code -1} that means the
-     * fixed-length streaming mode is disabled.
+     * The byte count in the request body if it is both known and streamed; and
+     * -1 otherwise. If the byte count exceeds {@link Integer#MAX_VALUE} (2 GiB)
+     * then the value of this field will be {@link Integer#MAX_VALUE}. In that
+     * case use {@link #fixedContentLengthLong} to access the exact byte count.
      */
     protected int fixedContentLength = -1;
 
+    /**
+     * The byte count in the request body if it is both known and streamed; and
+     * -1 otherwise. Prefer this field over the {@code int}-valued {@code
+     * fixedContentLength} on platforms that support both.
+     */
+    protected long fixedContentLengthLong = -1;
+
     // 2XX: generally "OK"
     // 3XX: relocation/redirect
     // 4XX: client error
@@ -475,7 +483,7 @@
     /**
      * Numeric status code, 500: Internal error
      *
-     * @deprecated Use {@link #HTTP_INTERNAL_ERROR}
+     * @deprecated Use {@link #HTTP_INTERNAL_ERROR} instead.
      */
     @Deprecated
     public static final int HTTP_SERVER_ERROR = 500;
@@ -737,9 +745,8 @@
     }
 
     /**
-     * If the length of a HTTP request body is known ahead, sets fixed length to
-     * enable streaming without buffering. Sets after connection will cause an
-     * exception.
+     * Configures this connection to stream the request body with the known
+     * fixed byte count of {@code contentLength}.
      *
      * @see #setChunkedStreamingMode
      * @param contentLength
@@ -748,8 +755,9 @@
      *             if already connected or another mode already set.
      * @throws IllegalArgumentException
      *             if {@code contentLength} is less than zero.
+     * @since 1.7
      */
-    public void setFixedLengthStreamingMode(int contentLength) {
+    public void setFixedLengthStreamingMode(long contentLength) {
         if (super.connected) {
             throw new IllegalStateException("Already connected");
         }
@@ -759,7 +767,16 @@
         if (contentLength < 0) {
             throw new IllegalArgumentException("contentLength < 0");
         }
-        this.fixedContentLength = contentLength;
+        this.fixedContentLength = (int) Math.min(contentLength, Integer.MAX_VALUE);
+        this.fixedContentLengthLong = contentLength;
+    }
+
+    /**
+     * Equivalent to {@code setFixedLengthStreamingMode((long) contentLength)},
+     * but available on earlier versions of Android and limited to 2 GiB.
+     */
+    public void setFixedLengthStreamingMode(int contentLength) {
+      setFixedLengthStreamingMode((long) contentLength);
     }
 
     /**
@@ -787,7 +804,7 @@
             throw new IllegalStateException("Already in fixed-length mode");
         }
         if (chunkLength <= 0) {
-            this.chunkLength = HttpEngine.DEFAULT_CHUNK_LENGTH;
+            this.chunkLength = DEFAULT_CHUNK_LENGTH;
         } else {
             this.chunkLength = chunkLength;
         }
diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java
index bbe34c2..98ad098 100644
--- a/luni/src/main/java/java/net/InetAddress.java
+++ b/luni/src/main/java/java/net/InetAddress.java
@@ -495,7 +495,6 @@
     /**
      * Returns the IPv6 loopback address {@code ::1} or the IPv4 loopback address {@code 127.0.0.1}.
      * @since 1.7
-     * @hide 1.7
      */
     public static InetAddress getLoopbackAddress() {
         return Inet6Address.LOOPBACK;
diff --git a/luni/src/main/java/java/net/InetSocketAddress.java b/luni/src/main/java/java/net/InetSocketAddress.java
index 4f4a348..a366133 100644
--- a/luni/src/main/java/java/net/InetSocketAddress.java
+++ b/luni/src/main/java/java/net/InetSocketAddress.java
@@ -145,8 +145,9 @@
     }
 
     /**
-     * Returns the hostname, doing a reverse lookup on the {@code InetAddress} if no
-     * hostname string was provided at construction time.
+     * Returns the hostname, doing a reverse DNS lookup on the {@code InetAddress} if no
+     * hostname string was provided at construction time. Use {@link #getHostString} to
+     * avoid the reverse DNS lookup.
      */
     public final String getHostName() {
         return (addr != null) ? addr.getHostName() : hostname;
@@ -156,7 +157,6 @@
      * Returns the hostname if known, or the result of {@code InetAddress.getHostAddress}.
      * Unlike {@link #getHostName}, this method will never cause a DNS lookup.
      * @since 1.7
-     * @hide 1.7 - remember to add a link in the getHostName documentation!
      */
     public final String getHostString() {
         return (hostname != null) ? hostname : addr.getHostAddress();
diff --git a/luni/src/main/java/java/net/InetUnixAddress.java b/luni/src/main/java/java/net/InetUnixAddress.java
index 95bb097..44b9cba 100644
--- a/luni/src/main/java/java/net/InetUnixAddress.java
+++ b/luni/src/main/java/java/net/InetUnixAddress.java
@@ -16,7 +16,7 @@
 
 package java.net;
 
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 
 import static libcore.io.OsConstants.*;
 
@@ -29,7 +29,7 @@
    * Constructs an AF_UNIX InetAddress for the given path.
    */
   public InetUnixAddress(String path) {
-    this(path.getBytes(Charsets.UTF_8));
+    this(path.getBytes(StandardCharsets.UTF_8));
   }
 
   /**
@@ -43,6 +43,6 @@
    * Returns a string form of this InetAddress.
    */
   @Override public String toString() {
-    return "InetUnixAddress[" + new String(ipaddress, Charsets.UTF_8) + "]";
+    return "InetUnixAddress[" + new String(ipaddress, StandardCharsets.UTF_8) + "]";
   }
 }
diff --git a/luni/src/main/java/java/net/MulticastSocket.java b/luni/src/main/java/java/net/MulticastSocket.java
index 498a132..6f4a582 100644
--- a/luni/src/main/java/java/net/MulticastSocket.java
+++ b/luni/src/main/java/java/net/MulticastSocket.java
@@ -127,7 +127,7 @@
      * Returns the time-to-live (TTL) for multicast packets sent on this socket.
      *
      * @throws IOException if an error occurs.
-     * @deprecated Replaced by {@link #getTimeToLive}
+     * @deprecated Use {@link #getTimeToLive} instead.
      */
     @Deprecated
     public byte getTTL() throws IOException {
@@ -239,7 +239,7 @@
      * deprecated because it modifies the TTL socket option for this socket twice on each call.
      *
      * @throws IOException if an error occurs.
-     * @deprecated use {@link #setTimeToLive}.
+     * @deprecated Use {@link #setTimeToLive} instead.
      */
     @Deprecated
     public void send(DatagramPacket packet, byte ttl) throws IOException {
@@ -314,7 +314,7 @@
      * Valid TTL values are between 0 and 255 inclusive.
      *
      * @throws IOException if an error occurs.
-     * @deprecated Replaced by {@link #setTimeToLive}
+     * @deprecated Use {@link #setTimeToLive} instead.
      */
     @Deprecated
     public void setTTL(byte ttl) throws IOException {
diff --git a/luni/src/main/java/java/net/NetworkInterface.java b/luni/src/main/java/java/net/NetworkInterface.java
index ad81f32..b35424d 100644
--- a/luni/src/main/java/java/net/NetworkInterface.java
+++ b/luni/src/main/java/java/net/NetworkInterface.java
@@ -67,8 +67,7 @@
 
     /**
      * Returns the index for the network interface, or -1 if unknown.
-     *
-     * @hide 1.7
+     * @since 1.7
      */
     public int getIndex() {
         return interfaceIndex;
@@ -250,7 +249,7 @@
      * interface has this index.
      *
      * @throws SocketException if an error occurs.
-     * @hide 1.7
+     * @since 1.7
      */
     public static NetworkInterface getByIndex(int index) throws SocketException {
         String name = Libcore.os.if_indextoname(index);
diff --git a/luni/src/main/java/java/net/PlainSocketImpl.java b/luni/src/main/java/java/net/PlainSocketImpl.java
index e247ac3..18942d6 100644
--- a/luni/src/main/java/java/net/PlainSocketImpl.java
+++ b/luni/src/main/java/java/net/PlainSocketImpl.java
@@ -236,8 +236,8 @@
             return Streams.readSingleByte(this);
         }
 
-        @Override public int read(byte[] buffer, int offset, int byteCount) throws IOException {
-            return socketImpl.read(buffer, offset, byteCount);
+        @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+            return socketImpl.read(buffer, byteOffset, byteCount);
         }
     }
 
diff --git a/luni/src/main/java/java/net/ResponseSource.java b/luni/src/main/java/java/net/ResponseSource.java
deleted file mode 100644
index fb974e9..0000000
--- a/luni/src/main/java/java/net/ResponseSource.java
+++ /dev/null
@@ -1,45 +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.net;
-
-/**
- * Where the HTTP client should look for a response.
- *
- * @hide
- */
-public enum ResponseSource {
-
-    /**
-     * Return the response from the cache immediately.
-     */
-    CACHE,
-
-    /**
-     * Make a conditional request to the host, returning the cache response if
-     * the cache is valid and the network response otherwise.
-     */
-    CONDITIONAL_CACHE,
-
-    /**
-     * Return the response from the network.
-     */
-    NETWORK;
-
-    public boolean requiresConnection() {
-        return this == CONDITIONAL_CACHE || this == NETWORK;
-    }
-}
diff --git a/luni/src/main/java/java/net/ServerSocket.java b/luni/src/main/java/java/net/ServerSocket.java
index ba8d6269..399511f 100644
--- a/luni/src/main/java/java/net/ServerSocket.java
+++ b/luni/src/main/java/java/net/ServerSocket.java
@@ -17,6 +17,7 @@
 
 package java.net;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.nio.channels.ServerSocketChannel;
 
@@ -26,7 +27,7 @@
  * appropriate reply. The actual tasks that a server socket must accomplish are
  * implemented by an internal {@code SocketImpl} instance.
  */
-public class ServerSocket {
+public class ServerSocket implements Closeable {
     /**
      * The RI specifies that where the caller doesn't give an explicit backlog,
      * the default is 50. The OS disagrees, so we need to explicitly call listen(2).
diff --git a/luni/src/main/java/java/net/Socket.java b/luni/src/main/java/java/net/Socket.java
index 2d80586..36fdf28 100644
--- a/luni/src/main/java/java/net/Socket.java
+++ b/luni/src/main/java/java/net/Socket.java
@@ -17,6 +17,7 @@
 
 package java.net;
 
+import java.io.Closeable;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
@@ -27,7 +28,7 @@
 /**
  * Provides a client-side TCP socket.
  */
-public class Socket {
+public class Socket implements Closeable {
     private static SocketImplFactory factory;
 
     final SocketImpl impl;
@@ -941,12 +942,12 @@
      *
      * @see ServerSocket#implAccept
      */
-    void accepted() {
+    void accepted() throws SocketException {
         isCreated = isBound = isConnected = true;
         cacheLocalAddress();
     }
 
-    private void cacheLocalAddress() {
+    private void cacheLocalAddress() throws SocketException {
         this.localAddress = IoBridge.getSocketLocalAddress(impl.fd);
     }
 
diff --git a/luni/src/main/java/java/net/Socks4Message.java b/luni/src/main/java/java/net/Socks4Message.java
index c193520..f7b190d 100644
--- a/luni/src/main/java/java/net/Socks4Message.java
+++ b/luni/src/main/java/java/net/Socks4Message.java
@@ -18,7 +18,7 @@
 package java.net;
 
 import java.nio.ByteOrder;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import libcore.io.Memory;
 
 class Socks4Message {
@@ -188,7 +188,7 @@
         while (index < lastIndex && (buffer[index] != 0)) {
             index++;
         }
-        return new String(buffer, offset, index - offset, Charsets.ISO_8859_1);
+        return new String(buffer, offset, index - offset, StandardCharsets.ISO_8859_1);
     }
 
     /**
@@ -202,7 +202,7 @@
      * Put a string into the buffer at the offset given.
      */
     private void setString(int offset, int maxLength, String theString) {
-        byte[] stringBytes = theString.getBytes(Charsets.ISO_8859_1);
+        byte[] stringBytes = theString.getBytes(StandardCharsets.ISO_8859_1);
         int length = Math.min(stringBytes.length, maxLength);
         System.arraycopy(stringBytes, 0, buffer, offset, length);
         buffer[offset + length] = 0;
diff --git a/luni/src/main/java/java/net/URL.java b/luni/src/main/java/java/net/URL.java
index 9d44498..dd487bc 100644
--- a/luni/src/main/java/java/net/URL.java
+++ b/luni/src/main/java/java/net/URL.java
@@ -24,8 +24,6 @@
 import java.io.Serializable;
 import java.util.Hashtable;
 import java.util.jar.JarFile;
-import libcore.net.http.HttpHandler;
-import libcore.net.http.HttpsHandler;
 import libcore.net.url.FileHandler;
 import libcore.net.url.FtpHandler;
 import libcore.net.url.JarHandler;
@@ -427,9 +425,19 @@
         } else if (protocol.equals("ftp")) {
             streamHandler = new FtpHandler();
         } else if (protocol.equals("http")) {
-            streamHandler = new HttpHandler();
+            try {
+                String name = "com.android.okhttp.HttpHandler";
+                streamHandler = (URLStreamHandler) Class.forName(name).newInstance();
+            } catch (Exception e) {
+                throw new AssertionError(e);
+            }
         } else if (protocol.equals("https")) {
-            streamHandler = new HttpsHandler();
+            try {
+                String name = "com.android.okhttp.HttpsHandler";
+                streamHandler = (URLStreamHandler) Class.forName(name).newInstance();
+            } catch (Exception e) {
+                throw new AssertionError(e);
+            }
         } else if (protocol.equals("jar")) {
             streamHandler = new JarHandler();
         }
diff --git a/luni/src/main/java/java/net/URLClassLoader.java b/luni/src/main/java/java/net/URLClassLoader.java
index efb7531..88d2e25 100644
--- a/luni/src/main/java/java/net/URLClassLoader.java
+++ b/luni/src/main/java/java/net/URLClassLoader.java
@@ -26,7 +26,7 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.security.CodeSource;
 import java.security.PermissionCollection;
 import java.security.SecureClassLoader;
@@ -76,7 +76,7 @@
                 String parentURLString = getParentURL(url).toExternalForm();
                 String prefix = "jar:" + parentURLString + "/";
                 is = jf.getInputStream(indexEntry);
-                in = new BufferedReader(new InputStreamReader(is, Charsets.UTF_8));
+                in = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
                 HashMap<String, ArrayList<URL>> pre_map = new HashMap<String, ArrayList<URL>>();
                 // Ignore the 2 first lines (index version)
                 if (in.readLine() == null) return null;
diff --git a/luni/src/main/java/java/net/URLConnection.java b/luni/src/main/java/java/net/URLConnection.java
index 18a264e..74c15ce 100644
--- a/luni/src/main/java/java/net/URLConnection.java
+++ b/luni/src/main/java/java/net/URLConnection.java
@@ -347,7 +347,7 @@
     /**
      * Returns null.
      *
-     * @deprecated Use {@link #getRequestProperty}
+     * @deprecated Use {@link #getRequestProperty} instead.
      */
     @Deprecated
     public static String getDefaultRequestProperty(String field) {
@@ -829,7 +829,7 @@
     /**
      * Does nothing.
      *
-     * @deprecated Use {@link URLConnection#setRequestProperty(String, String)}.
+     * @deprecated Use {@link URLConnection#setRequestProperty(String, String)} instead.
      */
     @Deprecated
     public static void setDefaultRequestProperty(String field, String value) {
diff --git a/luni/src/main/java/java/net/URLDecoder.java b/luni/src/main/java/java/net/URLDecoder.java
index f21de7d..23dd8d0 100644
--- a/luni/src/main/java/java/net/URLDecoder.java
+++ b/luni/src/main/java/java/net/URLDecoder.java
@@ -38,7 +38,7 @@
      * @param s
      *            the encoded string.
      * @return the decoded clear-text representation of the given string.
-     * @deprecated use {@link #decode(String, String)} instead.
+     * @deprecated Use {@link #decode(String, String)} instead.
      */
     @Deprecated
     public static String decode(String s) {
diff --git a/luni/src/main/java/java/net/URLEncoder.java b/luni/src/main/java/java/net/URLEncoder.java
index 5dd85b0..0f94907 100644
--- a/luni/src/main/java/java/net/URLEncoder.java
+++ b/luni/src/main/java/java/net/URLEncoder.java
@@ -19,7 +19,7 @@
 
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import libcore.net.UriCodec;
 
 /**
@@ -43,11 +43,11 @@
     /**
      * Equivalent to {@code encode(s, "UTF-8")}.
      *
-     * @deprecated use {@link #encode(String, String)} instead.
+     * @deprecated Use {@link #encode(String, String)} instead.
      */
     @Deprecated
     public static String encode(String s) {
-        return ENCODER.encode(s, Charsets.UTF_8);
+        return ENCODER.encode(s, StandardCharsets.UTF_8);
     }
 
     /**
diff --git a/luni/src/main/java/java/net/URLStreamHandler.java b/luni/src/main/java/java/net/URLStreamHandler.java
index 4a04b6f..8a6c264 100644
--- a/luni/src/main/java/java/net/URLStreamHandler.java
+++ b/luni/src/main/java/java/net/URLStreamHandler.java
@@ -222,7 +222,7 @@
      *            the file component.
      * @param ref
      *            the reference.
-     * @deprecated use setURL(URL, String String, int, String, String, String,
+     * @deprecated Use setURL(URL, String String, int, String, String, String,
      *             String, String) instead.
      */
     @Deprecated
diff --git a/luni/src/main/java/java/nio/ByteBuffer.java b/luni/src/main/java/java/nio/ByteBuffer.java
index cd39a53..324369a 100644
--- a/luni/src/main/java/java/nio/ByteBuffer.java
+++ b/luni/src/main/java/java/nio/ByteBuffer.java
@@ -125,7 +125,7 @@
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
      */
-    public final byte[] array() {
+    @Override public final byte[] array() {
         return protectedArray();
     }
 
@@ -142,7 +142,7 @@
      * @exception UnsupportedOperationException
      *                if this buffer is not based on an array.
      */
-    public final int arrayOffset() {
+    @Override public final int arrayOffset() {
         return protectedArrayOffset();
     }
 
@@ -290,7 +290,7 @@
      * @exception ClassCastException
      *                if {@code other} is not a byte buffer.
      */
-    public int compareTo(ByteBuffer otherBuffer) {
+    @Override public int compareTo(ByteBuffer otherBuffer) {
         int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
                 : otherBuffer.remaining();
         int thisPos = position;
@@ -592,7 +592,7 @@
      */
     public abstract short getShort(int index);
 
-    public final boolean hasArray() {
+    @Override public final boolean hasArray() {
         return protectedHasArray();
     }
 
@@ -617,7 +617,7 @@
      *
      * @return {@code true} if this buffer is direct, {@code false} otherwise.
      */
-    public abstract boolean isDirect();
+    @Override public abstract boolean isDirect();
 
     /**
      * Returns the byte order used by this buffer when converting bytes from/to
diff --git a/luni/src/main/java/java/nio/ByteBufferAsCharBuffer.java b/luni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
index ef5c52d..16d0688 100644
--- a/luni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
+++ b/luni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
@@ -176,8 +176,7 @@
         return result;
     }
 
-    @Override
-    public CharSequence subSequence(int start, int end) {
+    @Override public CharBuffer subSequence(int start, int end) {
         checkStartEndRemaining(start, end);
         CharBuffer result = duplicate();
         result.limit(position + end);
diff --git a/luni/src/main/java/java/nio/CharArrayBuffer.java b/luni/src/main/java/java/nio/CharArrayBuffer.java
index 43a75a6..245a799 100644
--- a/luni/src/main/java/java/nio/CharArrayBuffer.java
+++ b/luni/src/main/java/java/nio/CharArrayBuffer.java
@@ -124,7 +124,7 @@
     return ByteOrder.nativeOrder();
   }
 
-  @Override public final CharSequence subSequence(int start, int end) {
+  @Override public final CharBuffer subSequence(int start, int end) {
     checkStartEndRemaining(start, end);
     CharBuffer result = duplicate();
     result.limit(position + end);
diff --git a/luni/src/main/java/java/nio/CharBuffer.java b/luni/src/main/java/java/nio/CharBuffer.java
index 5c6f0fc..57070a0 100644
--- a/luni/src/main/java/java/nio/CharBuffer.java
+++ b/luni/src/main/java/java/nio/CharBuffer.java
@@ -632,7 +632,7 @@
      * @exception IndexOutOfBoundsException
      *                if either {@code start} or {@code end} is invalid.
      */
-    public abstract CharSequence subSequence(int start, int end);
+    public abstract CharBuffer subSequence(int start, int end);
 
     /**
      * Returns a string representing the current remaining chars of this buffer.
diff --git a/luni/src/main/java/java/nio/CharSequenceAdapter.java b/luni/src/main/java/java/nio/CharSequenceAdapter.java
index 12bac31..f686827 100644
--- a/luni/src/main/java/java/nio/CharSequenceAdapter.java
+++ b/luni/src/main/java/java/nio/CharSequenceAdapter.java
@@ -139,8 +139,7 @@
         return new CharSequenceAdapter(sequence.subSequence(position, limit));
     }
 
-    @Override
-    public CharSequence subSequence(int start, int end) {
+    @Override public CharBuffer subSequence(int start, int end) {
         checkStartEndRemaining(start, end);
         CharSequenceAdapter result = copy(this);
         result.position = position + start;
diff --git a/luni/src/main/java/java/nio/DatagramChannelImpl.java b/luni/src/main/java/java/nio/DatagramChannelImpl.java
index a23010e..39f2128 100644
--- a/luni/src/main/java/java/nio/DatagramChannelImpl.java
+++ b/luni/src/main/java/java/nio/DatagramChannelImpl.java
@@ -98,13 +98,6 @@
     }
 
     /**
-     * Returns the local address to which the socket is bound.
-     */
-    InetAddress getLocalAddress() {
-        return IoBridge.getSocketLocalAddress(fd);
-    }
-
-    /**
      * @see java.nio.channels.DatagramChannel#isConnected()
      */
     @Override
@@ -266,6 +259,7 @@
                 if (sendCount > 0) {
                     source.position(oldPosition + sendCount);
                 }
+                isBound = true;
             } finally {
                 end(sendCount >= 0);
             }
@@ -420,9 +414,7 @@
     }
 
     @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
-        synchronized (blockingLock()) {
-            IoUtils.setBlocking(fd, blocking);
-        }
+        IoUtils.setBlocking(fd, blocking);
     }
 
     /*
@@ -514,12 +506,12 @@
             return channelImpl.connectAddress.getAddress();
         }
 
-        /**
-         * @see java.net.DatagramSocket#getLocalAddress()
-         */
-        @Override
-        public InetAddress getLocalAddress() {
-            return channelImpl.getLocalAddress();
+        @Override public InetAddress getLocalAddress() {
+            try {
+                return IoBridge.getSocketLocalAddress(channelImpl.fd);
+            } catch (SocketException ex) {
+                return null;
+            }
         }
 
         /**
diff --git a/luni/src/main/java/java/nio/FileChannelImpl.java b/luni/src/main/java/java/nio/FileChannelImpl.java
index 14e06b7..a1be7fb 100644
--- a/luni/src/main/java/java/nio/FileChannelImpl.java
+++ b/luni/src/main/java/java/nio/FileChannelImpl.java
@@ -234,13 +234,17 @@
             // and we only care about making our backing file longer here.
             try {
                 Libcore.os.ftruncate(fd, position + size);
-            } catch (ErrnoException errnoException) {
+            } catch (ErrnoException ftruncateException) {
                 // EINVAL can be thrown if we're dealing with non-regular
                 // files, for example, character devices such as /dev/zero.
                 // In those cases, we ignore the failed truncation and
                 // continue on.
-                if (errnoException.errno != EINVAL) {
-                    throw errnoException.rethrowAsIOException();
+                try {
+                    if (S_ISREG(Libcore.os.fstat(fd).st_mode) || ftruncateException.errno != EINVAL) {
+                        throw ftruncateException.rethrowAsIOException();
+                    }
+                } catch (ErrnoException fstatException) {
+                    throw fstatException.rethrowAsIOException();
                 }
             }
         }
diff --git a/luni/src/main/java/java/nio/SelectionKeyImpl.java b/luni/src/main/java/java/nio/SelectionKeyImpl.java
index 694770e..db171b8 100644
--- a/luni/src/main/java/java/nio/SelectionKeyImpl.java
+++ b/luni/src/main/java/java/nio/SelectionKeyImpl.java
@@ -87,11 +87,13 @@
         return selector;
     }
 
-    /*
-     * package private method for setting the ready operation by selector
+    /**
+     * Allows SelectorImpl to set the ready operations.
      */
     void setReadyOps(int readyOps) {
-        this.readyOps = readyOps;
+        // We mask here (rather than assert, say) so that SelectorImpl doesn't have to worry
+        // about what operations a key is interested in. SelectorImpl is already too complicated.
+        this.readyOps = readyOps & interestOps;
     }
 
     private void checkValid() {
diff --git a/luni/src/main/java/java/nio/SelectorImpl.java b/luni/src/main/java/java/nio/SelectorImpl.java
index 02fdf54..41a2a52 100644
--- a/luni/src/main/java/java/nio/SelectorImpl.java
+++ b/luni/src/main/java/java/nio/SelectorImpl.java
@@ -166,13 +166,13 @@
             synchronized (unmodifiableKeys) {
                 synchronized (selectedKeys) {
                     doCancel();
-                    boolean isBlock = (timeout != 0);
+                    boolean isBlocking = (timeout != 0);
                     synchronized (keysLock) {
                         preparePollFds();
                     }
                     int rc = -1;
                     try {
-                        if (isBlock) {
+                        if (isBlocking) {
                             begin();
                         }
                         try {
@@ -183,7 +183,7 @@
                             }
                         }
                     } finally {
-                        if (isBlock) {
+                        if (isBlocking) {
                             end();
                         }
                     }
@@ -254,24 +254,25 @@
             pollFd.userData = null;
 
             int ops = key.interestOpsNoCheck();
-            int selectedOp = 0;
+            int selectedOps = 0;
             if ((pollFd.revents & POLLIN) != 0) {
-                selectedOp = ops & (OP_ACCEPT | OP_READ);
-            } else if ((pollFd.revents & POLLOUT) != 0) {
+                selectedOps |= ops & (OP_ACCEPT | OP_READ);
+            }
+            if ((pollFd.revents & POLLOUT) != 0) {
                 if (key.isConnected()) {
-                    selectedOp = ops & OP_WRITE;
+                    selectedOps |= ops & OP_WRITE;
                 } else {
-                    selectedOp = ops & OP_CONNECT;
+                    selectedOps |= ops & OP_CONNECT;
                 }
             }
 
-            if (selectedOp != 0) {
+            if (selectedOps != 0) {
                 boolean wasSelected = mutableSelectedKeys.contains(key);
-                if (wasSelected && key.readyOps() != selectedOp) {
-                    key.setReadyOps(key.readyOps() | selectedOp);
+                if (wasSelected && key.readyOps() != selectedOps) {
+                    key.setReadyOps(key.readyOps() | selectedOps);
                     ++readyKeyCount;
                 } else if (!wasSelected) {
-                    key.setReadyOps(selectedOp);
+                    key.setReadyOps(selectedOps);
                     mutableSelectedKeys.add(key);
                     ++readyKeyCount;
                 }
diff --git a/luni/src/main/java/java/nio/ServerSocketChannelImpl.java b/luni/src/main/java/java/nio/ServerSocketChannelImpl.java
index 5331158..3fb61a3 100644
--- a/luni/src/main/java/java/nio/ServerSocketChannelImpl.java
+++ b/luni/src/main/java/java/nio/ServerSocketChannelImpl.java
@@ -31,7 +31,9 @@
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 import java.nio.channels.spi.SelectorProvider;
+import libcore.io.ErrnoException;
 import libcore.io.IoUtils;
+import static libcore.io.OsConstants.*;
 
 /**
  * The default ServerSocketChannel.
@@ -65,21 +67,17 @@
 
         // Create an empty socket channel. This will be populated by ServerSocketAdapter.accept.
         SocketChannelImpl result = new SocketChannelImpl(provider(), false);
-        boolean connected = false;
         try {
             begin();
             synchronized (acceptLock) {
-                synchronized (blockingLock()) {
-                    do {
-                        try {
-                            socket.implAccept(result);
-                            // select successfully, break out immediately.
-                            break;
-                        } catch (SocketTimeoutException e) {
-                            // continue to accept if the channel is in blocking mode.
-                            // TODO: does this make sense? why does blocking imply no timeouts?
-                        }
-                    } while (isBlocking());
+                try {
+                    socket.implAccept(result);
+                } catch (SocketTimeoutException e) {
+                    if (shouldThrowSocketTimeoutExceptionFromAccept(e)) {
+                        throw e;
+                    }
+                    // Otherwise, this is a non-blocking socket and there's nothing ready, so we'll
+                    // fall through and return null.
                 }
             }
         } finally {
@@ -88,10 +86,21 @@
         return result.socket().isConnected() ? result : null;
     }
 
-    @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
-        synchronized (blockingLock()) {
-            IoUtils.setBlocking(impl.getFD$(), blocking);
+    private boolean shouldThrowSocketTimeoutExceptionFromAccept(SocketTimeoutException e) {
+        if (isBlocking()) {
+            return true;
         }
+        Throwable cause = e.getCause();
+        if (cause instanceof ErrnoException) {
+            if (((ErrnoException) cause).errno == EAGAIN) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
+        IoUtils.setBlocking(impl.getFD$(), blocking);
     }
 
     synchronized protected void implCloseSelectableChannel() throws IOException {
diff --git a/luni/src/main/java/java/nio/SocketChannelImpl.java b/luni/src/main/java/java/nio/SocketChannelImpl.java
index 233daf0..714005f 100644
--- a/luni/src/main/java/java/nio/SocketChannelImpl.java
+++ b/luni/src/main/java/java/nio/SocketChannelImpl.java
@@ -177,7 +177,7 @@
             finished = IoBridge.connect(fd, normalAddr, port);
             isBound = finished;
         } catch (IOException e) {
-            if (e instanceof ConnectException && !isBlocking()) {
+            if (isEINPROGRESS(e)) {
                 status = SOCKET_STATUS_PENDING;
             } else {
                 if (isOpen()) {
@@ -209,6 +209,19 @@
         return finished;
     }
 
+    private boolean isEINPROGRESS(IOException e) {
+        if (isBlocking()) {
+            return false;
+        }
+        if (e instanceof ConnectException) {
+            Throwable cause = e.getCause();
+            if (cause instanceof ErrnoException) {
+                return ((ErrnoException) cause).errno == EINPROGRESS;
+            }
+        }
+        return false;
+    }
+
     private void initLocalAddressAndPort() {
         SocketAddress sa;
         try {
@@ -456,9 +469,7 @@
     }
 
     @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
-        synchronized (blockingLock()) {
-            IoUtils.setBlocking(fd, blocking);
-        }
+        IoUtils.setBlocking(fd, blocking);
     }
 
     /*
@@ -658,12 +669,12 @@
         }
 
         @Override
-        public int read(byte[] buffer, int offset, int byteCount) throws IOException {
-            Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+        public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+            Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
             if (!channel.isBlocking()) {
                 throw new IllegalBlockingModeException();
             }
-            ByteBuffer buf = ByteBuffer.wrap(buffer, offset, byteCount);
+            ByteBuffer buf = ByteBuffer.wrap(buffer, byteOffset, byteCount);
             return channel.read(buf);
         }
     }
diff --git a/luni/src/main/java/java/nio/channels/Channels.java b/luni/src/main/java/java/nio/channels/Channels.java
index b59eeac..e354743 100644
--- a/luni/src/main/java/java/nio/channels/Channels.java
+++ b/luni/src/main/java/java/nio/channels/Channels.java
@@ -216,8 +216,8 @@
             return Streams.readSingleByte(this);
         }
 
-        @Override public synchronized int read(byte[] target, int offset, int length) throws IOException {
-            ByteBuffer buffer = ByteBuffer.wrap(target, offset, length);
+        @Override public synchronized int read(byte[] target, int byteOffset, int byteCount) throws IOException {
+            ByteBuffer buffer = ByteBuffer.wrap(target, byteOffset, byteCount);
             checkBlocking(channel);
             return channel.read(buffer);
         }
diff --git a/luni/src/main/java/java/nio/channels/FileLock.java b/luni/src/main/java/java/nio/channels/FileLock.java
index 4cdcc27..360f826 100644
--- a/luni/src/main/java/java/nio/channels/FileLock.java
+++ b/luni/src/main/java/java/nio/channels/FileLock.java
@@ -68,7 +68,7 @@
  * Further care should be exercised when locking files maintained on network
  * file systems, since they often have further limitations.
  */
-public abstract class FileLock {
+public abstract class FileLock implements AutoCloseable {
 
     // The underlying file channel.
     private final FileChannel channel;
@@ -185,10 +185,16 @@
     public abstract void release() throws IOException;
 
     /**
-     * Returns a string that shows the details of the lock suitable for display
-     * to an end user.
+     * Calls {@link #release} for {@code AutoCloseable}.
      *
-     * @return the display string.
+     * @since 1.7
+     */
+    public final void close() throws IOException {
+        release();
+    }
+
+    /**
+     * Returns a string that shows the details of the lock suitable for debugging.
      */
     @Override
     public final String toString() {
diff --git a/luni/src/main/java/java/nio/channels/Selector.java b/luni/src/main/java/java/nio/channels/Selector.java
index 1aac14b..6d9b063 100644
--- a/luni/src/main/java/java/nio/channels/Selector.java
+++ b/luni/src/main/java/java/nio/channels/Selector.java
@@ -16,6 +16,7 @@
 
 package java.nio.channels;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.nio.channels.spi.SelectorProvider;
 import java.util.Set;
@@ -33,7 +34,7 @@
  * selector are checked to see whether they are ready for operation according to
  * their {@link SelectionKey interest set}.
  */
-public abstract class Selector {
+public abstract class Selector implements Closeable {
 
     /**
      * Returns a selector returned by {@link SelectorProvider#provider}'s
diff --git a/luni/src/main/java/java/nio/charset/Charset.java b/luni/src/main/java/java/nio/charset/Charset.java
index 400aa8b..02cd42f 100644
--- a/luni/src/main/java/java/nio/charset/Charset.java
+++ b/luni/src/main/java/java/nio/charset/Charset.java
@@ -371,9 +371,7 @@
     public abstract CharsetDecoder newDecoder();
 
     /**
-     * Gets the canonical name of this charset.
-     *
-     * @return this charset's name in canonical form.
+     * Returns the canonical name of this charset.
      */
     public final String name() {
         return this.canonicalName;
diff --git a/luni/src/main/java/java/nio/charset/CharsetDecoder.java b/luni/src/main/java/java/nio/charset/CharsetDecoder.java
index 1559db4..7aa546c 100644
--- a/luni/src/main/java/java/nio/charset/CharsetDecoder.java
+++ b/luni/src/main/java/java/nio/charset/CharsetDecoder.java
@@ -303,12 +303,8 @@
      *             method threw an <code>BufferUnderflowException</code> or
      *             <code>BufferOverflowException</code>.
      */
-    public final CoderResult decode(ByteBuffer in, CharBuffer out,
-            boolean endOfInput) {
-        /*
-         * status check
-         */
-        if ((status == FLUSH) || (!endOfInput && status == END)) {
+    public final CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput) {
+        if (status == FLUSH || (!endOfInput && status == END)) {
             throw new IllegalStateException();
         }
 
diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoder.java b/luni/src/main/java/java/nio/charset/CharsetEncoder.java
index 8f02f96..c2d74a1 100644
--- a/luni/src/main/java/java/nio/charset/CharsetEncoder.java
+++ b/luni/src/main/java/java/nio/charset/CharsetEncoder.java
@@ -163,65 +163,27 @@
     }
 
     /**
-     * Checks if the given character can be encoded by this encoder.
-     * <p>
-     * Note that this method can change the internal status of this encoder, so
+     * Tests whether the given character can be encoded by this encoder.
+     *
+     * <p>Note that this method may change the internal status of this encoder, so
      * it should not be called when another encoding process is ongoing,
      * otherwise it will throw an <code>IllegalStateException</code>.
-     * <p>
-     * This method can be overridden for performance improvement.
      *
-     * @param c
-     *            the given encoder.
-     * @return true if given character can be encoded by this encoder.
-     * @throws IllegalStateException
-     *             if another encode process is ongoing so that the current
-     *             internal status is neither RESET or FLUSH.
+     * @throws IllegalStateException if another encode process is ongoing.
      */
     public boolean canEncode(char c) {
-        return implCanEncode(CharBuffer.wrap(new char[] { c }));
-    }
-
-    // implementation of canEncode
-    private boolean implCanEncode(CharBuffer cb) {
-        if (status == FLUSH || status == INIT) {
-            status = READY;
-        }
-        if (status != READY) {
-            throw new IllegalStateException("encoding already in progress");
-        }
-        CodingErrorAction malformBak = malformedInputAction;
-        CodingErrorAction unmapBak = unmappableCharacterAction;
-        onMalformedInput(CodingErrorAction.REPORT);
-        onUnmappableCharacter(CodingErrorAction.REPORT);
-        boolean result = true;
-        try {
-            this.encode(cb);
-        } catch (CharacterCodingException e) {
-            result = false;
-        }
-        onMalformedInput(malformBak);
-        onUnmappableCharacter(unmapBak);
-        reset();
-        return result;
+        return canEncode(CharBuffer.wrap(new char[] { c }));
     }
 
     /**
-     * Checks if a given <code>CharSequence</code> can be encoded by this
+     * Tests whether the given <code>CharSequence</code> can be encoded by this
      * encoder.
      *
-     * Note that this method can change the internal status of this encoder, so
+     * <p>Note that this method may change the internal status of this encoder, so
      * it should not be called when another encode process is ongoing, otherwise
      * it will throw an <code>IllegalStateException</code>.
      *
-     * This method can be overridden for performance improvement.
-     *
-     * @param sequence
-     *            the given <code>CharSequence</code>.
-     * @return true if the given <code>CharSequence</code> can be encoded by
-     *         this encoder.
-     * @throws IllegalStateException
-     *             if current internal status is neither RESET or FLUSH.
+     * @throws IllegalStateException if another encode process is ongoing.
      */
     public boolean canEncode(CharSequence sequence) {
         CharBuffer cb;
@@ -230,7 +192,27 @@
         } else {
             cb = CharBuffer.wrap(sequence);
         }
-        return implCanEncode(cb);
+
+        if (status == FLUSH || status == INIT) {
+            status = READY;
+        }
+        if (status != READY) {
+            throw new IllegalStateException();
+        }
+        CodingErrorAction originalMalformedInputAction = malformedInputAction;
+        CodingErrorAction originalUnmappableCharacterAction = unmappableCharacterAction;
+        onMalformedInput(CodingErrorAction.REPORT);
+        onUnmappableCharacter(CodingErrorAction.REPORT);
+        try {
+            this.encode(cb);
+            return true;
+        } catch (CharacterCodingException e) {
+            return false;
+        } finally {
+            onMalformedInput(originalMalformedInputAction);
+            onUnmappableCharacter(originalUnmappableCharacterAction);
+            reset();
+        }
     }
 
     /**
@@ -272,54 +254,47 @@
      *             if other exception happened during the encode operation.
      */
     public final ByteBuffer encode(CharBuffer in) throws CharacterCodingException {
-        if (in.remaining() == 0) {
-            return ByteBuffer.allocate(0);
-        }
-        reset();
         int length = (int) (in.remaining() * averageBytesPerChar);
-        ByteBuffer output = ByteBuffer.allocate(length);
-        CoderResult result = null;
-        while (true) {
-            result = encode(in, output, false);
-            if (result==CoderResult.UNDERFLOW) {
-                break;
-            } else if (result==CoderResult.OVERFLOW) {
-                output = allocateMore(output);
-                continue;
-            }
-            checkCoderResult(result);
+        ByteBuffer out = ByteBuffer.allocate(length);
+        if (in.hasRemaining() == false) {
+            return out;
         }
-        result = encode(in, output, true);
-        checkCoderResult(result);
 
-        while (true) {
-            result = flush(output);
-            if (result==CoderResult.UNDERFLOW) {
-                output.flip();
+        reset();
+
+        while (in.hasRemaining()) {
+            CoderResult result = encode(in, out, true);
+            if (result == CoderResult.UNDERFLOW) {
                 break;
-            } else if (result==CoderResult.OVERFLOW) {
-                output = allocateMore(output);
+            } else if (result == CoderResult.OVERFLOW) {
+                out = allocateMore(out);
                 continue;
+            } else {
+                checkCoderResult(result);
             }
-            checkCoderResult(result);
-            output.flip();
-            if (result.isMalformed()) {
-                throw new MalformedInputException(result.length());
-            } else if (result.isUnmappable()) {
-                throw new UnmappableCharacterException(result.length());
+
+            result = flush(out);
+            if (result == CoderResult.UNDERFLOW) {
+                break;
+            } else if (result == CoderResult.OVERFLOW) {
+                out = allocateMore(out);
+                continue;
+            } else {
+                checkCoderResult(result);
             }
-            break;
         }
+
+        out.flip();
         status = READY;
         finished = true;
-        return output;
+        return out;
     }
 
     /*
      * checks the result whether it needs to throw CharacterCodingException.
      */
     private void checkCoderResult(CoderResult result) throws CharacterCodingException {
-        if (malformedInputAction == CodingErrorAction.REPORT && result.isMalformed() ) {
+        if (malformedInputAction == CodingErrorAction.REPORT && result.isMalformed()) {
             throw new MalformedInputException(result.length());
         } else if (unmappableCharacterAction == CodingErrorAction.REPORT && result.isUnmappable()) {
             throw new UnmappableCharacterException(result.length());
@@ -405,12 +380,14 @@
         if (status == READY && finished && !endOfInput) {
             throw new IllegalStateException();
         }
-        if ((status == FLUSH) || (!endOfInput && status == END)) {
+        if (status == FLUSH || (!endOfInput && status == END)) {
             throw new IllegalStateException();
         }
 
-        CoderResult result;
+        status = endOfInput ? END : ONGOING;
+
         while (true) {
+            CoderResult result;
             try {
                 result = encodeLoop(in, out);
             } catch (BufferOverflowException e) {
@@ -418,37 +395,25 @@
             } catch (BufferUnderflowException e) {
                 throw new CoderMalfunctionError(e);
             }
-            if (result==CoderResult.UNDERFLOW) {
-                status = endOfInput ? END : ONGOING;
-                if (endOfInput) {
-                    int remaining = in.remaining();
-                    if (remaining > 0) {
-                        result = CoderResult.malformedForLength(remaining);
-                    } else {
-                        return result;
-                    }
+            if (result == CoderResult.UNDERFLOW) {
+                if (endOfInput && in.hasRemaining()) {
+                    result = CoderResult.malformedForLength(in.remaining());
                 } else {
                     return result;
                 }
-            } else if (result==CoderResult.OVERFLOW) {
-                status = endOfInput ? END : ONGOING;
+            } else if (result == CoderResult.OVERFLOW) {
                 return result;
             }
-            CodingErrorAction action = malformedInputAction;
-            if (result.isUnmappable()) {
-                action = unmappableCharacterAction;
+            CodingErrorAction action =
+                    result.isUnmappable() ? unmappableCharacterAction : malformedInputAction;
+            if (action == CodingErrorAction.REPORT) {
+                return result;
             }
-            // If the action is IGNORE or REPLACE, we should continue
-            // encoding.
             if (action == CodingErrorAction.REPLACE) {
                 if (out.remaining() < replacementBytes.length) {
                     return CoderResult.OVERFLOW;
                 }
                 out.put(replacementBytes);
-            } else {
-                if (action != CodingErrorAction.IGNORE) {
-                    return result;
-                }
             }
             in.position(in.position() + result.length());
         }
@@ -467,9 +432,9 @@
      * {@link #encode(CharBuffer, ByteBuffer, boolean) encode}. When an
      * exception is encountered in the encoding operation, most implementations
      * of this method will return a relevant result object to the
-     * {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method, and some
-     * performance optimized implementation may handle the exception and
-     * implement the error action itself.
+     * {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method, and
+     * subclasses may handle the exception and
+     * implement the error action themselves.
      * <p>
      * The buffers are scanned from their current positions, and their positions
      * will be modified accordingly, while their marks and limits will be
@@ -588,18 +553,9 @@
     }
 
     /**
-     * Checks if the given argument is legal as this encoder's replacement byte
-     * array.
-     *
-     * The given byte array is legal if and only if it can be decode into
-     * sixteen bits Unicode characters.
-     *
-     * This method can be overridden for performance improvement.
-     *
-     * @param replacement
-     *            the given byte array to be checked.
-     * @return true if the the given argument is legal as this encoder's
-     *         replacement byte array.
+     * Tests whether the given argument is legal as this encoder's replacement byte
+     * array. The given byte array is legal if and only if it can be decoded into
+     * characters.
      */
     public boolean isLegalReplacement(byte[] replacement) {
         if (decoder == null) {
diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
index 76807b0..4bc4354 100644
--- a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
+++ b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
@@ -184,14 +184,6 @@
         }
     }
 
-    public boolean canEncode(char c) {
-        return canEncode((int) c);
-    }
-
-    public boolean canEncode(int codePoint) {
-        return NativeConverter.canEncode(converterHandle, codePoint);
-    }
-
     @Override protected void finalize() throws Throwable {
         try {
             NativeConverter.closeConverter(converterHandle);
diff --git a/luni/src/main/java/java/nio/charset/Charsets.java b/luni/src/main/java/java/nio/charset/Charsets.java
index 826b12a..3dede7a 100644
--- a/luni/src/main/java/java/nio/charset/Charsets.java
+++ b/luni/src/main/java/java/nio/charset/Charsets.java
@@ -17,31 +17,12 @@
 package java.nio.charset;
 
 /**
- * Provides convenient access to the most important built-in charsets. Saves a hash lookup and
- * unnecessary handling of UnsupportedEncodingException at call sites, compared to using the
- * charset's name.
- *
- * Also various special-case charset conversions (for performance).
+ * Various special-case charset conversions (for performance).
  *
  * @hide internal use only
  */
 public final class Charsets {
     /**
-     * A cheap and type-safe constant for the ISO-8859-1 Charset.
-     */
-    public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
-
-    /**
-     * A cheap and type-safe constant for the US-ASCII Charset.
-     */
-    public static final Charset US_ASCII = Charset.forName("US-ASCII");
-
-    /**
-     * A cheap and type-safe constant for the UTF-8 Charset.
-     */
-    public static final Charset UTF_8 = Charset.forName("UTF-8");
-
-    /**
      * Returns a new byte array containing the bytes corresponding to the given characters,
      * encoded in US-ASCII. Unrepresentable characters are replaced by (byte) '?'.
      */
diff --git a/luni/src/main/java/java/nio/charset/CoderResult.java b/luni/src/main/java/java/nio/charset/CoderResult.java
index 3cc2673..6c45e26 100644
--- a/luni/src/main/java/java/nio/charset/CoderResult.java
+++ b/luni/src/main/java/java/nio/charset/CoderResult.java
@@ -154,8 +154,6 @@
 
     /**
      * Returns true if this result is an underflow condition.
-     *
-     * @return true if an underflow, otherwise false.
      */
     public boolean isUnderflow() {
         return this.type == TYPE_UNDERFLOW;
@@ -164,19 +162,13 @@
     /**
      * Returns true if this result represents a malformed-input error or an
      * unmappable-character error.
-     *
-     * @return true if this is a malformed-input error or an
-     *         unmappable-character error, otherwise false.
      */
     public boolean isError() {
-        return this.type == TYPE_MALFORMED_INPUT
-                || this.type == TYPE_UNMAPPABLE_CHAR;
+        return this.type == TYPE_MALFORMED_INPUT || this.type == TYPE_UNMAPPABLE_CHAR;
     }
 
     /**
      * Returns true if this result represents a malformed-input error.
-     *
-     * @return true if this is a malformed-input error, otherwise false.
      */
     public boolean isMalformed() {
         return this.type == TYPE_MALFORMED_INPUT;
@@ -184,8 +176,6 @@
 
     /**
      * Returns true if this result is an overflow condition.
-     *
-     * @return true if this is an overflow, otherwise false.
      */
     public boolean isOverflow() {
         return this.type == TYPE_OVERFLOW;
@@ -193,18 +183,15 @@
 
     /**
      * Returns true if this result represents an unmappable-character error.
-     *
-     * @return true if this is an unmappable-character error, otherwise false.
      */
     public boolean isUnmappable() {
         return this.type == TYPE_UNMAPPABLE_CHAR;
     }
 
     /**
-     * Gets the length of the erroneous input. The length is only meaningful to
+     * Returns the length of the erroneous input. The length is only meaningful for
      * a malformed-input error or an unmappable character error.
      *
-     * @return the length, as an integer, of this object's erroneous input.
      * @throws UnsupportedOperationException
      *             if this result is an overflow or underflow.
      */
diff --git a/luni/src/main/java/java/nio/charset/StandardCharsets.java b/luni/src/main/java/java/nio/charset/StandardCharsets.java
new file mode 100644
index 0000000..66fa9f6
--- /dev/null
+++ b/luni/src/main/java/java/nio/charset/StandardCharsets.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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.nio.charset;
+
+/**
+ * Convenient access to the most important built-in charsets.
+ * @since 1.7
+ */
+public final class StandardCharsets {
+  private StandardCharsets() {
+  }
+
+  /**
+   * The ISO-8859-1 charset.
+   */
+  public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
+
+  /**
+   * The US-ASCII charset.
+   */
+  public static final Charset US_ASCII = Charset.forName("US-ASCII");
+
+  /**
+   * The UTF-8 charset.
+   */
+  public static final Charset UTF_8 = Charset.forName("UTF-8");
+
+  /**
+   * The UTF-16 charset.
+   */
+  public static final Charset UTF_16 = Charset.forName("UTF-16");
+
+  /**
+   * The UTF-16BE (big-endian) charset.
+   */
+  public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
+
+  /**
+   * The UTF-16LE (little-endian) charset.
+   */
+  public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
+}
diff --git a/luni/src/main/java/java/security/Certificate.java b/luni/src/main/java/java/security/Certificate.java
index afec0d3..1d410a1 100644
--- a/luni/src/main/java/java/security/Certificate.java
+++ b/luni/src/main/java/java/security/Certificate.java
@@ -27,7 +27,7 @@
  * validity of itself. It's in the responsibility of the application to verify
  * the validity of its certificates.
  *
- * @deprecated Replaced by behavior in {@link java.security.cert}
+ * @deprecated Use {@link java.security.cert.Certificate} instead.
  * @see java.security.cert.Certificate
  */
 @Deprecated
diff --git a/luni/src/main/java/java/security/DigestInputStream.java b/luni/src/main/java/java/security/DigestInputStream.java
index e7d97ca..655c11f 100644
--- a/luni/src/main/java/java/security/DigestInputStream.java
+++ b/luni/src/main/java/java/security/DigestInputStream.java
@@ -96,33 +96,26 @@
     }
 
     /**
-     * Reads {@code len} bytes into the specified {@code byte[]}, starting from
-     * the specified offset. Updates the digest if this function is
+     * Reads up to {@code byteCount} bytes into {@code buffer}, starting at
+     * {@code byteOffset}. Updates the digest if this function is
      * {@link #on(boolean)}.
-     * <p>
-     * This operation is blocking.
      *
-     * @param b
-     *            the byte array in which to store the bytes
-     * @param off
-     *            the initial position in {@code b} to store the bytes read from
-     *            this stream
-     * @param len
-     *            the maximum number of bytes to store in {@code b}
-     * @return the number of bytes actually read or -1 if the end of the
-     *         filtered stream has been reached while reading
+     * <p>This operation is blocking.
+     *
+     * <p>Returns the number of bytes actually read or -1 if the end of the
+     * filtered stream has been reached while reading.
+     *
      * @throws IOException
      *             if reading the source stream causes an {@code IOException}
      */
     @Override
-    public int read(byte[] b, int off, int len) throws IOException {
-        // read next up to len bytes
-        int bytesRead = in.read(b, off, len);
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+        int bytesRead = in.read(buffer, byteOffset, byteCount);
         // update digest only if
         // - digest functionality is on
         // - eos has not been reached
         if (isOn && (bytesRead != -1)) {
-            digest.update(b, off, bytesRead);
+            digest.update(buffer, byteOffset, bytesRead);
         }
         // return number of bytes read
         return bytesRead;
diff --git a/luni/src/main/java/java/security/Identity.java b/luni/src/main/java/java/security/Identity.java
index 6e5b8a3..f0eef5d 100644
--- a/luni/src/main/java/java/security/Identity.java
+++ b/luni/src/main/java/java/security/Identity.java
@@ -25,9 +25,8 @@
 /**
  * {@code Identity} represents an identity like a person or a company.
  *
- * @deprecated The functionality of this class has been replace by
- *             {@link Principal}, {@link KeyStore} and the {@code
- *             java.security.cert} package.
+ * @deprecated Use {@link Principal}, {@link KeyStore} and the {@code java.security.cert} package
+ * instead.
  */
 @Deprecated
 public abstract class Identity implements Principal, Serializable {
diff --git a/luni/src/main/java/java/security/IdentityScope.java b/luni/src/main/java/java/security/IdentityScope.java
index 1e344fd..ee17b58 100644
--- a/luni/src/main/java/java/security/IdentityScope.java
+++ b/luni/src/main/java/java/security/IdentityScope.java
@@ -23,9 +23,8 @@
 /**
  * {@code IdentityScope} represents a scope for {@link Identity} objects.
  *
- * @deprecated The functionality of this class has been replace by
- *             {@link Principal}, {@link KeyStore} and the {@code
- *             java.security.cert} package.
+ * @deprecated Use {@link Principal}, {@link KeyStore} and the {@code java.security.cert} package
+ * instead.
  */
 @Deprecated
 public abstract class IdentityScope extends Identity {
diff --git a/luni/src/main/java/java/security/Security.java b/luni/src/main/java/java/security/Security.java
index b5bd02a..0b6961b 100644
--- a/luni/src/main/java/java/security/Security.java
+++ b/luni/src/main/java/java/security/Security.java
@@ -17,7 +17,6 @@
 
 package java.security;
 
-
 import java.io.BufferedInputStream;
 import java.io.InputStream;
 import java.util.Enumeration;
@@ -72,11 +71,11 @@
 
     // Register default providers
     private static void registerDefaultProviders() {
-        secprops.put("security.provider.1", "org.apache.harmony.xnet.provider.jsse.OpenSSLProvider");
+        secprops.put("security.provider.1", "com.android.org.conscrypt.OpenSSLProvider");
         secprops.put("security.provider.2", "org.apache.harmony.security.provider.cert.DRLCertFactory");
-        secprops.put("security.provider.3", "org.bouncycastle.jce.provider.BouncyCastleProvider");
+        secprops.put("security.provider.3", "com.android.org.bouncycastle.jce.provider.BouncyCastleProvider");
         secprops.put("security.provider.4", "org.apache.harmony.security.provider.crypto.CryptoProvider");
-        secprops.put("security.provider.5", "org.apache.harmony.xnet.provider.jsse.JSSEProvider");
+        secprops.put("security.provider.5", "com.android.org.conscrypt.JSSEProvider");
     }
 
     /**
@@ -87,8 +86,7 @@
      * @param propName
      *            the name of the property.
      * @return value of the property.
-     * @deprecated Use {@link AlgorithmParameters} and {@link KeyFactory}
-     *             instead.
+     * @deprecated Use {@link AlgorithmParameters} and {@link KeyFactory} instead.
      */
     @Deprecated
     public static String getAlgorithmProperty(String algName, String propName) {
diff --git a/luni/src/main/java/java/security/Signature.java b/luni/src/main/java/java/security/Signature.java
index b2bd122..0372c33 100644
--- a/luni/src/main/java/java/security/Signature.java
+++ b/luni/src/main/java/java/security/Signature.java
@@ -523,7 +523,7 @@
      * @throws InvalidParameterException
      *             if the parameter is invalid, already set or is not allowed to
      *             be changed.
-     * @deprecated Use {@link #setParameter(AlgorithmParameterSpec)}
+     * @deprecated Use {@link #setParameter(AlgorithmParameterSpec)} instead.
      */
     @Deprecated
     public final void setParameter(String param, Object value)
@@ -565,7 +565,7 @@
      *         null}.
      * @throws InvalidParameterException
      *             if {@code param} is not a valid parameter for this {@code
-     *             Signature} or an other error occures.
+     *             Signature} or an other error occurs.
      * @deprecated There is no generally accepted parameter naming convention.
      */
     @Deprecated
diff --git a/luni/src/main/java/java/security/Signer.java b/luni/src/main/java/java/security/Signer.java
index b892090..8f8ef06 100644
--- a/luni/src/main/java/java/security/Signer.java
+++ b/luni/src/main/java/java/security/Signer.java
@@ -21,9 +21,8 @@
  * {@link Signer} represents an identity (individual or corporation) that owns a
  * private key and the corresponding public key.
  *
- * @deprecated Replaced by behavior in {@link java.security.cert
- *             java.security.cert} package and {@link java.security.Principal
- *             Principal}
+ * @deprecated Use the {@link java.security.cert java.security.cert} package
+ * and {@link java.security.Principal} instead.
  */
 @Deprecated
 public abstract class Signer extends Identity {
diff --git a/luni/src/main/java/java/security/security.properties b/luni/src/main/java/java/security/security.properties
index b124271..dd5830d 100644
--- a/luni/src/main/java/java/security/security.properties
+++ b/luni/src/main/java/java/security/security.properties
@@ -19,14 +19,14 @@
 # See also: J2SE doc. "How to Implement a Provider for the JavaTM Cryptography Architecture"
 #
 # Android's provider of OpenSSL backed implementations
-security.provider.1=org.apache.harmony.xnet.provider.jsse.OpenSSLProvider
+security.provider.1=com.android.org.conscrypt.OpenSSLProvider
 # Favor Harmony's CertificateFactory.X509 over BouncyCastle's
 security.provider.2=org.apache.harmony.security.provider.cert.DRLCertFactory
 # Android's stripped down BouncyCastle provider
 security.provider.3=com.android.org.bouncycastle.jce.provider.BouncyCastleProvider
 # Remaining Harmony providers
 security.provider.4=org.apache.harmony.security.provider.crypto.CryptoProvider
-security.provider.5=org.apache.harmony.xnet.provider.jsse.JSSEProvider
+security.provider.5=com.android.org.conscrypt.JSSEProvider
 
 
 
@@ -40,11 +40,11 @@
 # javax/net/ssl/SSLServerSocketFactory.html#getDefault()
 
 # For regular SSLSockets, we have two implementations:
-ssl.SocketFactory.provider=org.apache.harmony.xnet.provider.jsse.OpenSSLSocketFactoryImpl
-#ssl.SocketFactory.provider=org.apache.harmony.xnet.provider.jsse.SSLSocketFactoryImpl
+ssl.SocketFactory.provider=com.android.org.conscrypt.OpenSSLSocketFactoryImpl
+#ssl.SocketFactory.provider=com.android.org.conscrypt.SSLSocketFactoryImpl
 
 # For SSLServerSockets, there's only the new, OpenSSL-based implementation:
-ssl.ServerSocketFactory.provider=org.apache.harmony.xnet.provider.jsse.OpenSSLServerSocketFactoryImpl
+ssl.ServerSocketFactory.provider=com.android.org.conscrypt.OpenSSLSocketFactoryImpl
 
 # Default KeyStore type.
 # See specification for java/security/KeyStore.html#getDefaultType()
diff --git a/luni/src/main/java/java/sql/CallableStatement.java b/luni/src/main/java/java/sql/CallableStatement.java
index 5bd9c52..162841d 100644
--- a/luni/src/main/java/java/sql/CallableStatement.java
+++ b/luni/src/main/java/java/sql/CallableStatement.java
@@ -111,8 +111,7 @@
      *         the parameter in question is an SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @deprecated Use {@link #getBigDecimal(int)} or
-     *             {@link #getBigDecimal(String)}
+     * @deprecated Use {@link #getBigDecimal(int)} or {@link #getBigDecimal(String)} instead.
      */
     @Deprecated
     public BigDecimal getBigDecimal(int parameterIndex, int scale)
diff --git a/luni/src/main/java/java/sql/Date.java b/luni/src/main/java/java/sql/Date.java
index 34ca5bd..4aac326 100644
--- a/luni/src/main/java/java/sql/Date.java
+++ b/luni/src/main/java/java/sql/Date.java
@@ -41,7 +41,7 @@
      * Constructs a {@code Date} object corresponding to the supplied year,
      * month and day.
      *
-     * @deprecated Use the constructor {@link #Date(long)}.
+     * @deprecated Use the constructor {@link #Date(long)} instead.
      * @param theYear
      *            the year, specified as the year minus 1900. Must be in the
      *            range {@code [0,8099]}.
diff --git a/luni/src/main/java/java/sql/DriverManager.java b/luni/src/main/java/java/sql/DriverManager.java
index 550ccae..58fc068 100644
--- a/luni/src/main/java/java/sql/DriverManager.java
+++ b/luni/src/main/java/java/sql/DriverManager.java
@@ -281,7 +281,7 @@
      * Gets the log {@code PrintStream} used by the {@code DriverManager} and
      * all the JDBC Drivers.
      *
-     * @deprecated use {@link #getLogWriter()} instead.
+     * @deprecated Use {@link #getLogWriter()} instead.
      * @return the {@code PrintStream} used for logging activities.
      */
     @Deprecated
diff --git a/luni/src/main/java/java/sql/ResultSet.java b/luni/src/main/java/java/sql/ResultSet.java
index 64ecb59..12b681a 100644
--- a/luni/src/main/java/java/sql/ResultSet.java
+++ b/luni/src/main/java/java/sql/ResultSet.java
@@ -298,8 +298,7 @@
      * Gets the value of a column specified by column index as a {@code
      * java.math.BigDecimal}.
      *
-     * @deprecated use {@link #getBigDecimal(int)} or
-     *             {@link #getBigDecimal(String)}
+     * @deprecated Use {@link #getBigDecimal(int)} or {@link #getBigDecimal(String)} instead.
      * @param columnIndex
      *            the index of the column to read.
      * @param scale
@@ -328,8 +327,7 @@
      * Gets the value of a column specified by column name, as a {@code
      * java.math.BigDecimal}.
      *
-     * @deprecated use {@link #getBigDecimal(int)} or
-     *             {@link #getBigDecimal(String)}
+     * @deprecated Use {@link #getBigDecimal(int)} or {@link #getBigDecimal(String)} instead.
      * @param columnName
      *            the name of the column to read.
      * @param scale
@@ -1050,7 +1048,7 @@
      * Gets the value of the column as an {@code InputStream} of unicode
      * characters.
      *
-     * @deprecated Use {@link #getCharacterStream}.
+     * @deprecated Use {@link #getCharacterStream} instead.
      * @param columnIndex
      *            the index of the column to read.
      * @return an {@code InputStream} holding the value of the column. {@code
@@ -1065,7 +1063,7 @@
      * Gets the value of the column as an {@code InputStream} of Unicode
      * characters.
      *
-     * @deprecated Use {@link #getCharacterStream}
+     * @deprecated Use {@link #getCharacterStream} instead.
      * @param columnName
      *            the name of the column to read.
      * @return an {@code InputStream} holding the value of the column. {@code
diff --git a/luni/src/main/java/java/sql/Time.java b/luni/src/main/java/java/sql/Time.java
index 913379c..c6e2f20 100644
--- a/luni/src/main/java/java/sql/Time.java
+++ b/luni/src/main/java/java/sql/Time.java
@@ -39,7 +39,7 @@
      * <p>
      * The result is undefined if any argument is out of bounds.
      *
-     * @deprecated Use the constructor {@link #Time(long)}.
+     * @deprecated Use the constructor {@link #Time(long)} instead.
      * @param theHour
      *            a value in the range {@code [0,23]}.
      * @param theMinute
@@ -67,7 +67,7 @@
 
     /**
      * @deprecated This method is deprecated and must not be used. An SQL
-     *             {@code Time} object does not have a {@code Date} component.
+     *             {@code Time} object does not have a date component.
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
@@ -81,7 +81,7 @@
 
     /**
      * @deprecated This method is deprecated and must not be used. An SQL
-     *             {@code Time} object does not have a <i>Day</i> component.
+     *             {@code Time} object does not have a day component.
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
@@ -95,7 +95,7 @@
 
     /**
      * @deprecated This method is deprecated and must not be used. An SQL
-     *             {@code Time} object does not have a <i>Month</i> component.
+     *             {@code Time} object does not have a month component.
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
@@ -109,7 +109,7 @@
 
     /**
      * @deprecated This method is deprecated and must not be used. An SQL
-     *             {@code Time} object does not have a <i>Year</i> component.
+     *             {@code Time} object does not have a year component.
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
@@ -123,7 +123,7 @@
 
     /**
      * @deprecated This method is deprecated and must not be used. An SQL
-     *             {@code Time} object does not have a {@code Date} component.
+     *             {@code Time} object does not have a date component.
      * @throws IllegalArgumentException
      *             if this method is called.
      */
@@ -136,7 +136,7 @@
 
     /**
      * @deprecated This method is deprecated and must not be used. An SQL
-     *             {@code Time} object does not have a <i>Month</i> component.
+     *             {@code Time} object does not have a month component.
      * @throws IllegalArgumentException
      *             if this method is called.
      */
@@ -149,7 +149,7 @@
 
     /**
      * @deprecated This method is deprecated and must not be used. An SQL
-     *             {@code Time} object does not have a <i>Year</i> component.
+     *             {@code Time} object does not have a year component.
      * @throws IllegalArgumentException
      *             if this method is called.
      */
diff --git a/luni/src/main/java/java/sql/Timestamp.java b/luni/src/main/java/java/sql/Timestamp.java
index 2e6d3d9..f35fa9b 100644
--- a/luni/src/main/java/java/sql/Timestamp.java
+++ b/luni/src/main/java/java/sql/Timestamp.java
@@ -57,7 +57,7 @@
      * supplied values for <i>Year</i>, <i>Month</i>, <i>Date</i>, <i>Hour</i>,
      * <i>Minutes</i>, <i>Seconds</i> and <i>Nanoseconds</i>.
      *
-     * @deprecated Use the constructor {@link #Timestamp(long)}.
+     * @deprecated Use the constructor {@link #Timestamp(long)} instead.
      * @param theYear
      *            specified as the year minus 1900.
      * @param theMonth
diff --git a/luni/src/main/java/java/text/SimpleDateFormat.java b/luni/src/main/java/java/text/SimpleDateFormat.java
index a3dc722..04287ae 100644
--- a/luni/src/main/java/java/text/SimpleDateFormat.java
+++ b/luni/src/main/java/java/text/SimpleDateFormat.java
@@ -86,7 +86,7 @@
  * <tr> <td>{@code s}</td> <td>second in minute</td>        <td>(Number)</td>      <td>55</td> </tr>
  * <tr> <td>{@code w}</td> <td>week in year</td>            <td>(Number)</td>      <td>27</td> </tr>
  * <tr> <td>{@code y}</td> <td>year</td>                    <td>(Number)</td>      <td>{@code yy}:10 {@code y}/{@code yyy}/{@code yyyy}:2010</td> </tr>
- * <tr> <td>{@code z}</td> <td>time zone</td>               <td>(Timezone)</td>    <td>{@code z}/{@code zz}/{@code zzz}:PST {@code zzzz}:Pacific Standard Time</td> </tr>
+ * <tr> <td>{@code z}</td> <td>time zone</td>               <td>(Time Zone)</td>   <td>{@code z}/{@code zz}/{@code zzz}:PST {@code zzzz}:Pacific Standard Time</td> </tr>
  * <tr> <td>{@code '}</td> <td>escape for text</td>         <td>(Delimiter)</td>   <td>{@code 'Date='}:Date=</td> </tr>
  * <tr> <td>{@code ''}</td> <td>single quote</td>           <td>(Literal)</td>     <td>{@code 'o''clock'}:o'clock</td> </tr>
  * </table>
@@ -250,22 +250,6 @@
     }
 
     /**
-     * Validates the format character.
-     *
-     * @param format
-     *            the format character
-     *
-     * @throws IllegalArgumentException
-     *             when the format character is invalid
-     */
-    private void validateFormat(char format) {
-        int index = PATTERN_CHARS.indexOf(format);
-        if (index == -1) {
-            throw new IllegalArgumentException("Unknown pattern character '" + format + "'");
-        }
-    }
-
-    /**
      * Validates the pattern.
      *
      * @param template
@@ -285,7 +269,7 @@
             next = (template.charAt(i));
             if (next == '\'') {
                 if (count > 0) {
-                    validateFormat((char) last);
+                    validatePatternCharacter((char) last);
                     count = 0;
                 }
                 if (last == next) {
@@ -302,21 +286,21 @@
                     count++;
                 } else {
                     if (count > 0) {
-                        validateFormat((char) last);
+                        validatePatternCharacter((char) last);
                     }
                     last = next;
                     count = 1;
                 }
             } else {
                 if (count > 0) {
-                    validateFormat((char) last);
+                    validatePatternCharacter((char) last);
                     count = 0;
                 }
                 last = -1;
             }
         }
         if (count > 0) {
-            validateFormat((char) last);
+            validatePatternCharacter((char) last);
         }
 
         if (quote) {
@@ -324,6 +308,13 @@
         }
     }
 
+    private void validatePatternCharacter(char format) {
+        int index = PATTERN_CHARS.indexOf(format);
+        if (index == -1) {
+            throw new IllegalArgumentException("Unknown pattern character '" + format + "'");
+        }
+    }
+
     /**
      * Constructs a new {@code SimpleDateFormat} using the specified
      * non-localized pattern and {@code DateFormatSymbols} and the {@code
diff --git a/luni/src/main/java/java/util/Arrays.java b/luni/src/main/java/java/util/Arrays.java
index c1b2727..2c84795 100644
--- a/luni/src/main/java/java/util/Arrays.java
+++ b/luni/src/main/java/java/util/Arrays.java
@@ -150,6 +150,7 @@
      *            the array.
      * @return a {@code List} of the elements of the specified array.
      */
+    @SafeVarargs
     public static <T> List<T> asList(T... array) {
         return new ArrayList<T>(array);
     }
diff --git a/luni/src/main/java/java/util/BitSet.java b/luni/src/main/java/java/util/BitSet.java
index 9dfe35e..736f272 100644
--- a/luni/src/main/java/java/util/BitSet.java
+++ b/luni/src/main/java/java/util/BitSet.java
@@ -611,7 +611,7 @@
      * Returns the index of the first bit that is set on or before {@code index}, or -1 if
      * no lower bits are set or {@code index == -1}.
      * @throws IndexOutOfBoundsException if {@code index < -1}.
-     * @hide 1.7
+     * @since 1.7
      */
     public int previousSetBit(int index) {
         if (index == -1) {
@@ -631,7 +631,7 @@
      * Returns the index of the first bit that is clear on or before {@code index}, or -1 if
      * no lower bits are clear or {@code index == -1}.
      * @throws IndexOutOfBoundsException if {@code index < -1}.
-     * @hide 1.7
+     * @since 1.7
      */
     public int previousClearBit(int index) {
         if (index == -1) {
@@ -669,7 +669,7 @@
      * Equivalent to {@code BitSet.valueOf(LongBuffer.wrap(longs))}, but likely to be faster.
      * This is likely to be the fastest way to create a {@code BitSet} because it's closest
      * to the internal representation.
-     * @hide 1.7
+     * @since 1.7
      */
     public static BitSet valueOf(long[] longs) {
         return new BitSet(longs.clone());
@@ -678,7 +678,7 @@
     /**
      * Returns a {@code BitSet} corresponding to {@code longBuffer}, interpreted as a little-endian
      * sequence of bits. This method does not alter the {@code LongBuffer}.
-     * @hide 1.7
+     * @since 1.7
      */
     public static BitSet valueOf(LongBuffer longBuffer) {
         // The bulk get would mutate LongBuffer (even if we reset position later), and it's not
@@ -693,7 +693,7 @@
 
     /**
      * Equivalent to {@code BitSet.valueOf(ByteBuffer.wrap(bytes))}.
-     * @hide 1.7
+     * @since 1.7
      */
     public static BitSet valueOf(byte[] bytes) {
         return BitSet.valueOf(ByteBuffer.wrap(bytes));
@@ -702,7 +702,7 @@
     /**
      * Returns a {@code BitSet} corresponding to {@code byteBuffer}, interpreted as a little-endian
      * sequence of bits. This method does not alter the {@code ByteBuffer}.
-     * @hide 1.7
+     * @since 1.7
      */
     public static BitSet valueOf(ByteBuffer byteBuffer) {
         byteBuffer = byteBuffer.slice().order(ByteOrder.LITTLE_ENDIAN);
@@ -721,7 +721,7 @@
      * Returns a new {@code long[]} containing a little-endian representation of the bits of
      * this {@code BitSet}, suitable for passing to {@code valueOf} to reconstruct
      * this {@code BitSet}.
-     * @hide 1.7
+     * @since 1.7
      */
     public long[] toLongArray() {
         return Arrays.copyOf(bits, longCount);
@@ -731,7 +731,7 @@
      * Returns a new {@code byte[]} containing a little-endian representation the bits of
      * this {@code BitSet}, suitable for passing to {@code valueOf} to reconstruct
      * this {@code BitSet}.
-     * @hide 1.7
+     * @since 1.7
      */
     public byte[] toByteArray() {
         int bitCount = length();
diff --git a/luni/src/main/java/java/util/Collections.java b/luni/src/main/java/java/util/Collections.java
index 491642b..932dcc1 100644
--- a/luni/src/main/java/java/util/Collections.java
+++ b/luni/src/main/java/java/util/Collections.java
@@ -2435,7 +2435,7 @@
 
     /**
      * Returns an enumeration containing no elements.
-     * @hide 1.7
+     * @since 1.7
      */
     @SuppressWarnings("unchecked")
     public static <T> Enumeration<T> emptyEnumeration() {
@@ -2444,7 +2444,7 @@
 
     /**
      * Returns an iterator containing no elements.
-     * @hide 1.7
+     * @since 1.7
      */
     @SuppressWarnings("unchecked")
     public static <T> Iterator<T> emptyIterator() {
@@ -2453,7 +2453,7 @@
 
     /**
      * Returns a list iterator containing no elements.
-     * @hide 1.7
+     * @since 1.7
      */
     public static <T> ListIterator<T> emptyListIterator() {
         return Collections.<T>emptyList().listIterator();
@@ -2584,6 +2584,7 @@
      *             if at least one of the elements can't be inserted into the
      *             collection.
      */
+    @SafeVarargs
     public static <T> boolean addAll(Collection<? super T> c, T... a) {
         boolean modified = false;
         for (int i = 0; i < a.length; i++) {
diff --git a/luni/src/main/java/java/util/ConcurrentModificationException.java b/luni/src/main/java/java/util/ConcurrentModificationException.java
index 5e5126a..634011f 100644
--- a/luni/src/main/java/java/util/ConcurrentModificationException.java
+++ b/luni/src/main/java/java/util/ConcurrentModificationException.java
@@ -51,7 +51,6 @@
      * Constructs a new {@code ConcurrentModificationException} with the given detail
      * message and cause.
      * @since 1.7
-     * @hide 1.7
      */
     public ConcurrentModificationException(String detailMessage, Throwable cause) {
         super(detailMessage, cause);
@@ -60,7 +59,6 @@
     /**
      * Constructs a new {@code ConcurrentModificationException} with the given cause.
      * @since 1.7
-     * @hide 1.7
      */
     public ConcurrentModificationException(Throwable cause) {
         super(cause);
diff --git a/luni/src/main/java/java/util/Currency.java b/luni/src/main/java/java/util/Currency.java
index ceda24e..b5b04a0 100644
--- a/luni/src/main/java/java/util/Currency.java
+++ b/luni/src/main/java/java/util/Currency.java
@@ -91,7 +91,6 @@
     /**
      * Returns a set of all known currencies.
      * @since 1.7
-     * @hide 1.7
      */
     public static Set<Currency> getAvailableCurrencies() {
         Set<Currency> result = new LinkedHashSet<Currency>();
@@ -113,7 +112,6 @@
      * Equivalent to {@code getDisplayName(Locale.getDefault())}.
      * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
      * @since 1.7
-     * @hide 1.7
      */
     public String getDisplayName() {
         return getDisplayName(Locale.getDefault());
@@ -123,7 +121,6 @@
      * Returns the localized name of this currency in the given {@code locale}.
      * Returns the ISO 4217 currency code if no localized name is available.
      * @since 1.7
-     * @hide 1.7
      */
     public String getDisplayName(Locale locale) {
         return ICU.getCurrencyDisplayName(locale.toString(), currencyCode);
diff --git a/luni/src/main/java/java/util/Date.java b/luni/src/main/java/java/util/Date.java
index da9f296..b4de055 100644
--- a/luni/src/main/java/java/util/Date.java
+++ b/luni/src/main/java/java/util/Date.java
@@ -69,8 +69,7 @@
      * @param day
      *            the day of the month, 1 - 31.
      *
-     * @deprecated use
-     *             {@link GregorianCalendar#GregorianCalendar(int, int, int)}
+     * @deprecated Use {@link GregorianCalendar#GregorianCalendar(int, int, int)} instead.
      */
     @Deprecated
     public Date(int year, int month, int day) {
@@ -94,8 +93,7 @@
      * @param minute
      *            the minute of the hour, 0 - 59.
      *
-     * @deprecated use
-     *             {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int)}
+     * @deprecated Use {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int)} instead.
      */
     @Deprecated
     public Date(int year, int month, int day, int hour, int minute) {
@@ -121,8 +119,8 @@
      * @param second
      *            the second of the minute, 0 - 59.
      *
-     * @deprecated use
-     *             {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int, int)}
+     * @deprecated Use {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int, int)}
+     * instead.
      */
     @Deprecated
     public Date(int year, int month, int day, int hour, int minute, int second) {
@@ -149,7 +147,7 @@
      * @param string
      *            the String to parse.
      *
-     * @deprecated use {@link DateFormat}
+     * @deprecated Use {@link DateFormat} instead.
      */
     @Deprecated
     public Date(String string) {
@@ -238,7 +236,7 @@
      *
      * @return the day of the month.
      *
-     * @deprecated use {@code Calendar.get(Calendar.DATE)}
+     * @deprecated Use {@code Calendar.get(Calendar.DATE)} instead.
      */
     @Deprecated
     public int getDate() {
@@ -250,7 +248,7 @@
      *
      * @return the day of the week.
      *
-     * @deprecated use {@code Calendar.get(Calendar.DAY_OF_WEEK)}
+     * @deprecated Use {@code Calendar.get(Calendar.DAY_OF_WEEK)} instead.
      */
     @Deprecated
     public int getDay() {
@@ -262,7 +260,7 @@
      *
      * @return the hour of the day.
      *
-     * @deprecated use {@code Calendar.get(Calendar.HOUR_OF_DAY)}
+     * @deprecated Use {@code Calendar.get(Calendar.HOUR_OF_DAY)} instead.
      */
     @Deprecated
     public int getHours() {
@@ -274,7 +272,7 @@
      *
      * @return the minutes.
      *
-     * @deprecated use {@code Calendar.get(Calendar.MINUTE)}
+     * @deprecated Use {@code Calendar.get(Calendar.MINUTE)} instead.
      */
     @Deprecated
     public int getMinutes() {
@@ -286,7 +284,7 @@
      *
      * @return the month.
      *
-     * @deprecated use {@code Calendar.get(Calendar.MONTH)}
+     * @deprecated Use {@code Calendar.get(Calendar.MONTH)} instead.
      */
     @Deprecated
     public int getMonth() {
@@ -298,7 +296,7 @@
      *
      * @return the seconds.
      *
-     * @deprecated use {@code Calendar.get(Calendar.SECOND)}
+     * @deprecated Use {@code Calendar.get(Calendar.SECOND)} instead.
      */
     @Deprecated
     public int getSeconds() {
@@ -320,8 +318,7 @@
      *
      * @return the timezone offset in minutes of the default {@code TimeZone}.
      *
-     * @deprecated use
-     *             {@code (Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / 60000}
+     * @deprecated Use {@code (Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / 60000} instead.
      */
     @Deprecated
     public int getTimezoneOffset() {
@@ -334,7 +331,7 @@
      *
      * @return the year - 1900.
      *
-     * @deprecated use {@code Calendar.get(Calendar.YEAR) - 1900}
+     * @deprecated Use {@code Calendar.get(Calendar.YEAR) - 1900} instead.
      */
     @Deprecated
     public int getYear() {
@@ -376,7 +373,7 @@
      *            the String to parse.
      * @return the millisecond value parsed from the String.
      *
-     * @deprecated use {@link DateFormat}
+     * @deprecated Use {@link DateFormat} instead.
      */
     @Deprecated
     public static long parse(String string) {
@@ -569,7 +566,7 @@
      * @param day
      *            the day of the month.
      *
-     * @deprecated use {@code Calendar.set(Calendar.DATE, day)}
+     * @deprecated Use {@code Calendar.set(Calendar.DATE, day)} instead.
      */
     @Deprecated
     public void setDate(int day) {
@@ -584,7 +581,7 @@
      * @param hour
      *            the hour of the day.
      *
-     * @deprecated use {@code Calendar.set(Calendar.HOUR_OF_DAY, hour)}
+     * @deprecated Use {@code Calendar.set(Calendar.HOUR_OF_DAY, hour)} instead.
      */
     @Deprecated
     public void setHours(int hour) {
@@ -599,7 +596,7 @@
      * @param minute
      *            the minutes.
      *
-     * @deprecated use {@code Calendar.set(Calendar.MINUTE, minute)}
+     * @deprecated Use {@code Calendar.set(Calendar.MINUTE, minute)} instead.
      */
     @Deprecated
     public void setMinutes(int minute) {
@@ -614,7 +611,7 @@
      * @param month
      *            the month.
      *
-     * @deprecated use {@code Calendar.set(Calendar.MONTH, month)}
+     * @deprecated Use {@code Calendar.set(Calendar.MONTH, month)} instead.
      */
     @Deprecated
     public void setMonth(int month) {
@@ -629,7 +626,7 @@
      * @param second
      *            the seconds.
      *
-     * @deprecated use {@code Calendar.set(Calendar.SECOND, second)}
+     * @deprecated Use {@code Calendar.set(Calendar.SECOND, second)} instead.
      */
     @Deprecated
     public void setSeconds(int second) {
@@ -655,7 +652,7 @@
      * @param year
      *            the year since 1900.
      *
-     * @deprecated use {@code Calendar.set(Calendar.YEAR, year + 1900)}
+     * @deprecated Use {@code Calendar.set(Calendar.YEAR, year + 1900)} instead.
      */
     @Deprecated
     public void setYear(int year) {
@@ -668,7 +665,7 @@
      * Returns the string representation of this {@code Date} in GMT in the format
      * {@code "22 Jun 1999 13:02:00 GMT"}.
      *
-     * @deprecated use {@link DateFormat}
+     * @deprecated Use {@link DateFormat} instead.
      */
     @Deprecated
     public String toGMTString() {
@@ -683,7 +680,7 @@
     /**
      * Returns the string representation of this {@code Date} for the default {@code Locale}.
      *
-     * @deprecated use {@link DateFormat}
+     * @deprecated Use {@link DateFormat} instead.
      */
     @Deprecated
     public String toLocaleString() {
@@ -749,7 +746,7 @@
      *            the second of the minute, 0 - 59.
      * @return the date and time in GMT in milliseconds.
      *
-     * @deprecated use: <code>
+     * @deprecated Use code like this instead:<code>
      *  Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
      *  cal.set(year + 1900, month, day, hour, minute, second);
      *  cal.getTime().getTime();</code>
diff --git a/luni/src/main/java/java/util/EnumSet.java b/luni/src/main/java/java/util/EnumSet.java
index 20be6f7..0393511 100644
--- a/luni/src/main/java/java/util/EnumSet.java
+++ b/luni/src/main/java/java/util/EnumSet.java
@@ -259,6 +259,7 @@
      * @throws NullPointerException
      *             if any of the specified elements is {@code null}.
      */
+    @SafeVarargs
     public static <E extends Enum<E>> EnumSet<E> of(E start, E... others) {
         EnumSet<E> set = of(start);
         for (E e : others) {
diff --git a/luni/src/main/java/java/util/Formatter.java b/luni/src/main/java/java/util/Formatter.java
index d6b772a..98bdccc 100644
--- a/luni/src/main/java/java/util/Formatter.java
+++ b/luni/src/main/java/java/util/Formatter.java
@@ -291,7 +291,7 @@
  * </tr>
  * <tr>
  * <td width="5%">{@code n}</td>
- * <td width="25%">Newline. (The value of the "line.separator" system property}.)</td>
+ * <td width="25%">Newline. (The value of {@link System#lineSeparator}.)</td>
  * <td width="30%">{@code format("first%nsecond");}</td>
  * <td width="30%">{@code first\nsecond}</td>
  * </tr>
diff --git a/luni/src/main/java/java/util/NavigableMap.java b/luni/src/main/java/java/util/NavigableMap.java
index beeb651..8530530 100644
--- a/luni/src/main/java/java/util/NavigableMap.java
+++ b/luni/src/main/java/java/util/NavigableMap.java
@@ -55,7 +55,7 @@
  * implement {@code NavigableMap}, but extensions and implementations
  * of this interface are encouraged to override these methods to return
  * {@code NavigableMap}.  Similarly,
- * {@link #keySet()} can be overriden to return {@code NavigableSet}.
+ * {@link #keySet()} can be overridden to return {@code NavigableSet}.
  *
  * @author Doug Lea
  * @author Josh Bloch
@@ -183,18 +183,12 @@
     /**
      * Returns a key-value mapping associated with the least
      * key in this map, or {@code null} if the map is empty.
-     *
-     * @return an entry with the least key,
-     *         or {@code null} if this map is empty
      */
     Map.Entry<K,V> firstEntry();
 
     /**
      * Returns a key-value mapping associated with the greatest
      * key in this map, or {@code null} if the map is empty.
-     *
-     * @return an entry with the greatest key,
-     *         or {@code null} if this map is empty
      */
     Map.Entry<K,V> lastEntry();
 
diff --git a/luni/src/main/java/java/util/Objects.java b/luni/src/main/java/java/util/Objects.java
new file mode 100644
index 0000000..2bfcef5
--- /dev/null
+++ b/luni/src/main/java/java/util/Objects.java
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+package java.util;
+
+import java.util.Arrays;
+
+/**
+ * Utility methods for objects.
+ * @since 1.7
+ */
+public final class Objects {
+  private Objects() {}
+
+  /**
+   * Returns 0 if {@code a == b}, or {@code c.compare(a, b)} otherwise.
+   * That is, this makes {@code c} null-safe.
+   */
+  public static <T> int compare(T a, T b, Comparator<? super T> c) {
+    if (a == b) {
+      return 0;
+    }
+    return c.compare(a, b);
+  }
+
+  /**
+   * Returns true if both arguments are null,
+   * the result of {@link Arrays#equals} if both arguments are primitive arrays,
+   * the result of {@link Arrays#deepEquals} if both arguments are arrays of reference types,
+   * and the result of {@link #equals} otherwise.
+   */
+  public static boolean deepEquals(Object a, Object b) {
+    if (a == null || b == null) {
+      return a == b;
+    } else if (a instanceof Object[] && b instanceof Object[]) {
+      return Arrays.deepEquals((Object[]) a, (Object[]) b);
+    } else if (a instanceof boolean[] && b instanceof boolean[]) {
+      return Arrays.equals((boolean[]) a, (boolean[]) b);
+    } else if (a instanceof byte[] && b instanceof byte[]) {
+      return Arrays.equals((byte[]) a, (byte[]) b);
+    } else if (a instanceof char[] && b instanceof char[]) {
+      return Arrays.equals((char[]) a, (char[]) b);
+    } else if (a instanceof double[] && b instanceof double[]) {
+      return Arrays.equals((double[]) a, (double[]) b);
+    } else if (a instanceof float[] && b instanceof float[]) {
+      return Arrays.equals((float[]) a, (float[]) b);
+    } else if (a instanceof int[] && b instanceof int[]) {
+      return Arrays.equals((int[]) a, (int[]) b);
+    } else if (a instanceof long[] && b instanceof long[]) {
+      return Arrays.equals((long[]) a, (long[]) b);
+    } else if (a instanceof short[] && b instanceof short[]) {
+      return Arrays.equals((short[]) a, (short[]) b);
+    }
+    return a.equals(b);
+  }
+
+  /**
+   * Null-safe equivalent of {@code a.equals(b)}.
+   */
+  public static boolean equals(Object a, Object b) {
+    return (a == null) ? (b == null) : a.equals(b);
+  }
+
+  /**
+   * Convenience wrapper for {@link Arrays#hashCode}, adding varargs.
+   * This can be used to compute a hash code for an object's fields as follows:
+   * {@code Objects.hash(a, b, c)}.
+   */
+  public static int hash(Object... values) {
+    return Arrays.hashCode(values);
+  }
+
+  /**
+   * Returns 0 for null or {@code o.hashCode()}.
+   */
+  public static int hashCode(Object o) {
+    return (o == null) ? 0 : o.hashCode();
+  }
+
+  /**
+   * Returns {@code o} if non-null, or throws {@code NullPointerException}.
+   */
+  public static <T> T requireNonNull(T o) {
+    if (o == null) {
+      throw new NullPointerException();
+    }
+    return o;
+  }
+
+  /**
+   * Returns {@code o} if non-null, or throws {@code NullPointerException}
+   * with the given detail message.
+   */
+  public static <T> T requireNonNull(T o, String message) {
+    if (o == null) {
+      throw new NullPointerException(message);
+    }
+    return o;
+  }
+
+  /**
+   * Returns "null" for null or {@code o.toString()}.
+   */
+  public static String toString(Object o) {
+    return (o == null) ? "null" : o.toString();
+  }
+
+  /**
+   * Returns {@code nullString} for null or {@code o.toString()}.
+   */
+  public static String toString(Object o, String nullString) {
+    return (o == null) ? nullString : o.toString();
+  }
+}
diff --git a/luni/src/main/java/java/util/Properties.java b/luni/src/main/java/java/util/Properties.java
index 57c6a00..cd19295 100644
--- a/luni/src/main/java/java/util/Properties.java
+++ b/luni/src/main/java/java/util/Properties.java
@@ -486,7 +486,7 @@
      * @throws ClassCastException if the key or value of a mapping is not a
      *                String.
      * @deprecated This method ignores any {@code IOException} thrown while
-     *             writing -- use {@link #store} instead for better exception
+     *             writing &mdash; use {@link #store} instead for better exception
      *             handling.
      */
     @Deprecated
diff --git a/luni/src/main/java/java/util/ResourceBundle.java b/luni/src/main/java/java/util/ResourceBundle.java
index f5c8285..a9c5824 100644
--- a/luni/src/main/java/java/util/ResourceBundle.java
+++ b/luni/src/main/java/java/util/ResourceBundle.java
@@ -24,8 +24,7 @@
 import java.io.InputStreamReader;
 import java.net.URL;
 import java.net.URLConnection;
-import java.nio.charset.Charsets;
-import static java.nio.charset.Charsets.UTF_8;
+import java.nio.charset.StandardCharsets;
 import libcore.io.IoUtils;
 
 /**
@@ -518,7 +517,7 @@
                     : ClassLoader.getSystemResourceAsStream(fileName);
             if (stream != null) {
                 try {
-                    bundle = new PropertyResourceBundle(new InputStreamReader(stream, UTF_8));
+                    bundle = new PropertyResourceBundle(new InputStreamReader(stream, StandardCharsets.UTF_8));
                     bundle.setLocale(locale);
                 } catch (IOException ignored) {
                 } finally {
diff --git a/luni/src/main/java/java/util/Scanner.java b/luni/src/main/java/java/util/Scanner.java
index 5f7d0e3..972e6f9 100644
--- a/luni/src/main/java/java/util/Scanner.java
+++ b/luni/src/main/java/java/util/Scanner.java
@@ -31,6 +31,7 @@
 import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.Charset;
 import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
 import java.text.NumberFormat;
 import java.util.regex.MatchResult;
 import java.util.regex.Matcher;
@@ -39,62 +40,49 @@
 
 /**
  * A parser that parses a text string of primitive types and strings with the
- * help of regular expressions. It supports localized numbers and various
+ * help of regular expressions. This class is not as useful as it might seem.
+ * It's very inefficient for communicating between machines; you should use JSON,
+ * protobufs, or even XML for that. Very simple uses might get away with {@link String#split}.
+ * For input from humans, the use of locale-specific regular expressions make it not only
+ * expensive but also somewhat unpredictable.
+ *
+ * <p>This class supports localized numbers and various
  * radixes. The input is broken into tokens by the delimiter pattern, which is
- * whitespace by default. The primitive types can be obtained via corresponding
- * next* methods. If the token is not in a valid format, an
- * {@code InputMismatchException} is thrown.
- * <p>
- * For example:
+ * {@code \\p{javaWhitespace}} by default.
+ *
+ * <p>Example:
  * <pre>
  * Scanner s = new Scanner("1A true");
- * System.out.println(s.nextInt(16));
- * System.out.println(s.nextBoolean());
+ * assertEquals(26, s.nextInt(16));
+ * assertEquals(true, s.nextBoolean());
  * </pre>
- * <p>
- * Yields the result: {@code 26 true}
- * <p>A {@code Scanner} can also find or skip specific patterns without regard for the
- * delimiter. All these methods and the various next* and hasNext* methods may
- * block.
- * <p>
- * The {@code Scanner} class is not thread-safe.
+ *
+ * <p>The {@code Scanner} class is not thread-safe.
  */
-public final class Scanner implements Iterator<String> {
+public final class Scanner implements Closeable, Iterator<String> {
+
+    private static final String NL = "\n|\r\n|\r|\u0085|\u2028|\u2029";
 
     // Default delimiting pattern.
-    private static final Pattern DEFAULT_DELIMITER = Pattern
-            .compile("\\p{javaWhitespace}+");
+    private static final Pattern DEFAULT_DELIMITER = Pattern.compile("\\p{javaWhitespace}+");
 
     // The boolean's pattern.
-    private static final Pattern BOOLEAN_PATTERN = Pattern.compile(
-            "true|false", Pattern.CASE_INSENSITIVE);
+    private static final Pattern BOOLEAN_PATTERN = Pattern.compile("true|false", Pattern.CASE_INSENSITIVE);
 
     // Pattern used to recognize line terminator.
-    private static final Pattern LINE_TERMINATOR;
+    private static final Pattern LINE_TERMINATOR = Pattern.compile(NL);
 
     // Pattern used to recognize multiple line terminators.
-    private static final Pattern MULTI_LINE_TERMINATOR;
+    private static final Pattern MULTI_LINE_TERMINATOR = Pattern.compile("(" + NL + ")+");
 
     // Pattern used to recognize a line with a line terminator.
-    private static final Pattern LINE_PATTERN;
-
-    static {
-        String NL = "\n|\r\n|\r|\u0085|\u2028|\u2029";
-        LINE_TERMINATOR = Pattern.compile(NL);
-        MULTI_LINE_TERMINATOR = Pattern.compile("(" + NL + ")+");
-        LINE_PATTERN = Pattern.compile(".*(" + NL + ")|.+(" + NL + ")?");
-    }
+    private static final Pattern LINE_PATTERN = Pattern.compile(".*(" + NL + ")|.+(" + NL + ")?");
 
     // The pattern matches anything.
     private static final Pattern ANY_PATTERN = Pattern.compile("(?s).*");
 
-    private static final int DIPLOID = 2;
-
-    // Default radix.
     private static final int DEFAULT_RADIX = 10;
 
-    private static final int DEFAULT_TRUNK_SIZE = 1024;
-
     // The input source of scanner.
     private Readable input;
 
@@ -104,7 +92,7 @@
 
     private Matcher matcher;
 
-    private int integerRadix = DEFAULT_RADIX;
+    private int currentRadix = DEFAULT_RADIX;
 
     private Locale locale = Locale.getDefault();
 
@@ -117,8 +105,7 @@
     // The length of the buffer.
     private int bufferLength = 0;
 
-    // Record the status of this scanner. True if the scanner
-    // is closed.
+    // Record the status of this scanner. True if the scanner is closed.
     private boolean closed = false;
 
     private IOException lastIOException;
@@ -130,9 +117,13 @@
     // Records whether the underlying readable has more input.
     private boolean inputExhausted = false;
 
-    private Object cacheHasNextValue = null;
+    private Object cachedNextValue = null;
+    private int cachedNextIndex = -1;
 
-    private int cachehasNextIndex = -1;
+    private Pattern cachedFloatPattern = null;
+
+    private int cachedIntegerPatternRadix = -1;
+    private Pattern cachedIntegerPattern = null;
 
     private enum DataType {
         /*
@@ -327,8 +318,8 @@
      *             if the {@code Scanner} is closed.
      */
     public String findInLine(Pattern pattern) {
-        checkClosed();
-        checkNull(pattern);
+        checkOpen();
+        checkNotNull(pattern);
         int horizonLineSeparator = 0;
 
         matcher.usePattern(MULTI_LINE_TERMINATOR);
@@ -405,7 +396,7 @@
     }
 
     /**
-     * Compiles the pattern string and tries to find a substing matching it in the input data. The
+     * Compiles the pattern string and tries to find a substring matching it in the input data. The
      * delimiter will be ignored. This is the same as invoking
      * {@code findInLine(Pattern.compile(pattern))}.
      *
@@ -455,8 +446,8 @@
      *             if {@code horizon} is less than zero.
      */
     public String findWithinHorizon(Pattern pattern, int horizon) {
-        checkClosed();
-        checkNull(pattern);
+        checkOpen();
+        checkNotNull(pattern);
         if (horizon < 0) {
             throw new IllegalArgumentException("horizon < 0");
         }
@@ -559,8 +550,8 @@
      *             if the {@code Scanner} has been closed.
      */
     public boolean hasNext(Pattern pattern) {
-        checkClosed();
-        checkNull(pattern);
+        checkOpen();
+        checkNotNull(pattern);
         matchSuccessful = false;
         saveCurrentStatus();
         // if the next token exists, set the match region, otherwise return
@@ -573,7 +564,7 @@
         boolean hasNext = false;
         // check whether next token matches the specified pattern
         if (matcher.matches()) {
-            cachehasNextIndex = findStartIndex;
+            cachedNextIndex = findStartIndex;
             matchSuccessful = true;
             hasNext = true;
         }
@@ -614,7 +605,7 @@
             String floatString = matcher.group();
             floatString = removeLocaleInfoFromFloat(floatString);
             try {
-                cacheHasNextValue = new BigDecimal(floatString);
+                cachedNextValue = new BigDecimal(floatString);
                 isBigDecimalValue = true;
             } catch (NumberFormatException e) {
                 matchSuccessful = false;
@@ -633,7 +624,7 @@
      *             if the {@code Scanner} has been closed.
      */
     public boolean hasNextBigInteger() {
-        return hasNextBigInteger(integerRadix);
+        return hasNextBigInteger(currentRadix);
     }
 
     /**
@@ -655,7 +646,7 @@
             String intString = matcher.group();
             intString = removeLocaleInfo(intString, DataType.INT);
             try {
-                cacheHasNextValue = new BigInteger(intString, radix);
+                cachedNextValue = new BigInteger(intString, radix);
                 isBigIntegerValue = true;
             } catch (NumberFormatException e) {
                 matchSuccessful = false;
@@ -687,7 +678,7 @@
      *             if the {@code Scanner} has been closed.
      */
     public boolean hasNextByte() {
-        return hasNextByte(integerRadix);
+        return hasNextByte(currentRadix);
     }
 
     /**
@@ -709,7 +700,7 @@
             String intString = matcher.group();
             intString = removeLocaleInfo(intString, DataType.INT);
             try {
-                cacheHasNextValue = Byte.valueOf(intString, radix);
+                cachedNextValue = Byte.valueOf(intString, radix);
                 isByteValue = true;
             } catch (NumberFormatException e) {
                 matchSuccessful = false;
@@ -734,7 +725,7 @@
             String floatString = matcher.group();
             floatString = removeLocaleInfoFromFloat(floatString);
             try {
-                cacheHasNextValue = Double.valueOf(floatString);
+                cachedNextValue = Double.valueOf(floatString);
                 isDoubleValue = true;
             } catch (NumberFormatException e) {
                 matchSuccessful = false;
@@ -759,7 +750,7 @@
             String floatString = matcher.group();
             floatString = removeLocaleInfoFromFloat(floatString);
             try {
-                cacheHasNextValue = Float.valueOf(floatString);
+                cachedNextValue = Float.valueOf(floatString);
                 isFloatValue = true;
             } catch (NumberFormatException e) {
                 matchSuccessful = false;
@@ -778,7 +769,7 @@
      *             if the {@code Scanner} has been closed,
      */
     public boolean hasNextInt() {
-        return hasNextInt(integerRadix);
+        return hasNextInt(currentRadix);
     }
 
     /**
@@ -801,7 +792,7 @@
             String intString = matcher.group();
             intString = removeLocaleInfo(intString, DataType.INT);
             try {
-                cacheHasNextValue = Integer.valueOf(intString, radix);
+                cachedNextValue = Integer.valueOf(intString, radix);
                 isIntValue = true;
             } catch (NumberFormatException e) {
                 matchSuccessful = false;
@@ -820,7 +811,7 @@
      *             if the {@code Scanner} is closed.
      */
     public boolean hasNextLine() {
-        checkClosed();
+        checkOpen();
         matcher.usePattern(LINE_PATTERN);
         matcher.region(findStartIndex, bufferLength);
 
@@ -856,7 +847,7 @@
      *             if the {@code Scanner} has been closed.
      */
     public boolean hasNextLong() {
-        return hasNextLong(integerRadix);
+        return hasNextLong(currentRadix);
     }
 
     /**
@@ -878,7 +869,7 @@
             String intString = matcher.group();
             intString = removeLocaleInfo(intString, DataType.INT);
             try {
-                cacheHasNextValue = Long.valueOf(intString, radix);
+                cachedNextValue = Long.valueOf(intString, radix);
                 isLongValue = true;
             } catch (NumberFormatException e) {
                 matchSuccessful = false;
@@ -897,7 +888,7 @@
      *             if the {@code Scanner} has been closed.
      */
     public boolean hasNextShort() {
-        return hasNextShort(integerRadix);
+        return hasNextShort(currentRadix);
     }
 
     /**
@@ -919,7 +910,7 @@
             String intString = matcher.group();
             intString = removeLocaleInfo(intString, DataType.INT);
             try {
-                cacheHasNextValue = Short.valueOf(intString, radix);
+                cachedNextValue = Short.valueOf(intString, radix);
                 isShortValue = true;
             } catch (NumberFormatException e) {
                 matchSuccessful = false;
@@ -930,23 +921,27 @@
 
     /**
      * Returns the last {@code IOException} that was raised while reading from the underlying
-     * input.
-     *
-     * @return the last thrown {@code IOException}, or {@code null} if none was thrown.
+     * input, or {@code null} if none was thrown.
      */
     public IOException ioException() {
         return lastIOException;
     }
 
     /**
-     * Return the {@code Locale} of this {@code Scanner}.
-     *
-     * @return the {@code Locale} of this {@code Scanner}.
+     * Returns the {@code Locale} of this {@code Scanner}.
      */
     public Locale locale() {
         return locale;
     }
 
+    private void setLocale(Locale locale) {
+        this.locale = locale;
+        this.decimalFormat = null;
+        this.cachedFloatPattern = null;
+        this.cachedIntegerPatternRadix = -1;
+        this.cachedIntegerPattern = null;
+    }
+
     /**
      * Returns the result of the last matching operation.
      * <p>
@@ -966,7 +961,7 @@
     }
 
     /**
-     * Returns the next token. The token will be both prefixed and postfixed by
+     * Returns the next token. The token will be both prefixed and suffixed by
      * the delimiter that is currently being used (or a string that matches the
      * delimiter pattern). This method will block if input is being read.
      *
@@ -982,7 +977,7 @@
 
     /**
      * Returns the next token if it matches the specified pattern. The token
-     * will be both prefixed and postfixed by the delimiter that is currently
+     * will be both prefixed and suffixed by the delimiter that is currently
      * being used (or a string that matches the delimiter pattern). This method will block
      * if input is being read.
      *
@@ -997,8 +992,8 @@
      *             if the next token does not match the pattern given.
      */
     public String next(Pattern pattern) {
-        checkClosed();
-        checkNull(pattern);
+        checkOpen();
+        checkNotNull(pattern);
         matchSuccessful = false;
         saveCurrentStatus();
         if (!setTokenRegion()) {
@@ -1018,7 +1013,7 @@
 
     /**
      * Returns the next token if it matches the specified pattern. The token
-     * will be both prefixed and postfixed by the delimiter that is currently
+     * will be both prefixed and suffixed by the delimiter that is currently
      * being used (or a string that matches the delimiter pattern). This method will block
      * if input is being read. Calling this method is equivalent to
      * {@code next(Pattern.compile(pattern))}.
@@ -1057,11 +1052,11 @@
      *             {@code BigDecimal}.
      */
     public BigDecimal nextBigDecimal() {
-        checkClosed();
-        Object obj = cacheHasNextValue;
-        cacheHasNextValue = null;
+        checkOpen();
+        Object obj = cachedNextValue;
+        cachedNextValue = null;
         if (obj instanceof BigDecimal) {
-            findStartIndex = cachehasNextIndex;
+            findStartIndex = cachedNextIndex;
             return (BigDecimal) obj;
         }
         Pattern floatPattern = getFloatPattern();
@@ -1079,10 +1074,9 @@
     }
 
     /**
-     * Returns the next token as a {@code BigInteger}. This method will block if input is
-     * being read. Equivalent to {@code nextBigInteger(DEFAULT_RADIX)}.
+     * Returns the next token as a {@code BigInteger} in the current radix.
+     * This method may block for more input.
      *
-     * @return the next token as {@code BigInteger}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
      * @throws NoSuchElementException
@@ -1092,7 +1086,7 @@
      *             {@code BigInteger}.
      */
     public BigInteger nextBigInteger() {
-        return nextBigInteger(integerRadix);
+        return nextBigInteger(currentRadix);
     }
 
     /**
@@ -1119,11 +1113,11 @@
      *             {@code BigInteger}.
      */
     public BigInteger nextBigInteger(int radix) {
-        checkClosed();
-        Object obj = cacheHasNextValue;
-        cacheHasNextValue = null;
+        checkOpen();
+        Object obj = cachedNextValue;
+        cachedNextValue = null;
         if (obj instanceof BigInteger) {
-            findStartIndex = cachehasNextIndex;
+            findStartIndex = cachedNextIndex;
             return (BigInteger) obj;
         }
         Pattern integerPattern = getIntegerPattern(radix);
@@ -1158,10 +1152,9 @@
     }
 
     /**
-     * Returns the next token as a {@code byte}. This method will block if input is being
-     * read. Equivalent to {@code nextByte(DEFAULT_RADIX)}.
+     * Returns the next token as a {@code byte} in the current radix.
+     * This method may block for more input.
      *
-     * @return the next token as a {@code byte}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
      * @throws NoSuchElementException
@@ -1171,7 +1164,7 @@
      *             {@code byte} value.
      */
     public byte nextByte() {
-        return nextByte(integerRadix);
+        return nextByte(currentRadix);
     }
 
     /**
@@ -1198,11 +1191,11 @@
      */
     @SuppressWarnings("boxing")
     public byte nextByte(int radix) {
-        checkClosed();
-        Object obj = cacheHasNextValue;
-        cacheHasNextValue = null;
+        checkOpen();
+        Object obj = cachedNextValue;
+        cachedNextValue = null;
         if (obj instanceof Byte) {
-            findStartIndex = cachehasNextIndex;
+            findStartIndex = cachedNextIndex;
             return (Byte) obj;
         }
         Pattern integerPattern = getIntegerPattern(radix);
@@ -1242,11 +1235,11 @@
      */
     @SuppressWarnings("boxing")
     public double nextDouble() {
-        checkClosed();
-        Object obj = cacheHasNextValue;
-        cacheHasNextValue = null;
+        checkOpen();
+        Object obj = cachedNextValue;
+        cachedNextValue = null;
         if (obj instanceof Double) {
-            findStartIndex = cachehasNextIndex;
+            findStartIndex = cachedNextIndex;
             return (Double) obj;
         }
         Pattern floatPattern = getFloatPattern();
@@ -1286,11 +1279,11 @@
      */
     @SuppressWarnings("boxing")
     public float nextFloat() {
-        checkClosed();
-        Object obj = cacheHasNextValue;
-        cacheHasNextValue = null;
+        checkOpen();
+        Object obj = cachedNextValue;
+        cachedNextValue = null;
         if (obj instanceof Float) {
-            findStartIndex = cachehasNextIndex;
+            findStartIndex = cachedNextIndex;
             return (Float) obj;
         }
         Pattern floatPattern = getFloatPattern();
@@ -1308,10 +1301,9 @@
     }
 
     /**
-     * Returns the next token as an {@code int}. This method will block if input is being
-     * read. Equivalent to {@code nextInt(DEFAULT_RADIX)}.
+     * Returns the next token as an {@code int} in the current radix.
+     * This method may block for more input.
      *
-     * @return the next token as an {@code int}
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
      * @throws NoSuchElementException
@@ -1321,7 +1313,7 @@
      *             {@code int} value.
      */
     public int nextInt() {
-        return nextInt(integerRadix);
+        return nextInt(currentRadix);
     }
 
     /**
@@ -1349,11 +1341,11 @@
      */
     @SuppressWarnings("boxing")
     public int nextInt(int radix) {
-        checkClosed();
-        Object obj = cacheHasNextValue;
-        cacheHasNextValue = null;
+        checkOpen();
+        Object obj = cachedNextValue;
+        cachedNextValue = null;
         if (obj instanceof Integer) {
-            findStartIndex = cachehasNextIndex;
+            findStartIndex = cachedNextIndex;
             return (Integer) obj;
         }
         Pattern integerPattern = getIntegerPattern(radix);
@@ -1384,7 +1376,7 @@
      *             if no line can be found, e.g. when input is an empty string.
      */
     public String nextLine() {
-        checkClosed();
+        checkOpen();
 
         matcher.usePattern(LINE_PATTERN);
         matcher.region(findStartIndex, bufferLength);
@@ -1420,10 +1412,9 @@
     }
 
     /**
-     * Returns the next token as a {@code long}. This method will block if input is being
-     * read. Equivalent to {@code nextLong(DEFAULT_RADIX)}.
+     * Returns the next token as a {@code long} in the current radix.
+     * This method may block for more input.
      *
-     * @return the next token as a {@code long}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
      * @throws NoSuchElementException
@@ -1433,7 +1424,7 @@
      *             {@code long} value.
      */
     public long nextLong() {
-        return nextLong(integerRadix);
+        return nextLong(currentRadix);
     }
 
     /**
@@ -1461,11 +1452,11 @@
      */
     @SuppressWarnings("boxing")
     public long nextLong(int radix) {
-        checkClosed();
-        Object obj = cacheHasNextValue;
-        cacheHasNextValue = null;
+        checkOpen();
+        Object obj = cachedNextValue;
+        cachedNextValue = null;
         if (obj instanceof Long) {
-            findStartIndex = cachehasNextIndex;
+            findStartIndex = cachedNextIndex;
             return (Long) obj;
         }
         Pattern integerPattern = getIntegerPattern(radix);
@@ -1483,10 +1474,9 @@
     }
 
     /**
-     * Returns the next token as a {@code short}. This method will block if input is being
-     * read. Equivalent to {@code nextShort(DEFAULT_RADIX)}.
+     * Returns the next token as a {@code short} in the current radix.
+     * This method may block for more input.
      *
-     * @return the next token as a {@code short}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
      * @throws NoSuchElementException
@@ -1496,7 +1486,7 @@
      *             {@code short} value.
      */
     public short nextShort() {
-        return nextShort(integerRadix);
+        return nextShort(currentRadix);
     }
 
     /**
@@ -1524,11 +1514,11 @@
      */
     @SuppressWarnings("boxing")
     public short nextShort(int radix) {
-        checkClosed();
-        Object obj = cacheHasNextValue;
-        cacheHasNextValue = null;
+        checkOpen();
+        Object obj = cachedNextValue;
+        cachedNextValue = null;
         if (obj instanceof Short) {
-            findStartIndex = cachehasNextIndex;
+            findStartIndex = cachedNextIndex;
             return (Short) obj;
         }
         Pattern integerPattern = getIntegerPattern(radix);
@@ -1551,7 +1541,7 @@
      * @return the radix of this {@code Scanner}
      */
     public int radix() {
-        return integerRadix;
+        return currentRadix;
     }
 
     /**
@@ -1571,8 +1561,8 @@
      *             if the specified pattern match fails.
      */
     public Scanner skip(Pattern pattern) {
-        checkClosed();
-        checkNull(pattern);
+        checkOpen();
+        checkNotNull(pattern);
         matcher.usePattern(pattern);
         matcher.region(findStartIndex, bufferLength);
         while (true) {
@@ -1666,7 +1656,7 @@
         if (l == null) {
             throw new NullPointerException("l == null");
         }
-        this.locale = l;
+        setLocale(l);
         return this;
     }
 
@@ -1679,7 +1669,7 @@
      */
     public Scanner useRadix(int radix) {
         checkRadix(radix);
-        this.integerRadix = radix;
+        this.currentRadix = radix;
         return this;
     }
 
@@ -1703,26 +1693,18 @@
      * Initialize some components.
      */
     private void initialization() {
-        buffer = CharBuffer.allocate(DEFAULT_TRUNK_SIZE);
+        buffer = CharBuffer.allocate(1024);
         buffer.limit(0);
         matcher = delimiter.matcher(buffer);
     }
 
-    /*
-     * Check the {@code Scanner}'s state, if it is closed, IllegalStateException will be
-     * thrown.
-     */
-    private void checkClosed() {
+    private void checkOpen() {
         if (closed) {
             throw new IllegalStateException();
         }
     }
 
-    /*
-     * Check the inputed pattern. If it is null, then a NullPointerException
-     * will be thrown out.
-     */
-    private void checkNull(Pattern pattern) {
+    private void checkNotNull(Pattern pattern) {
         if (pattern == null) {
             throw new NullPointerException("pattern == null");
         }
@@ -1754,93 +1736,82 @@
         findStartIndex = preStartIndex;
     }
 
-    /*
-     * Get integer's pattern
-     */
     private Pattern getIntegerPattern(int radix) {
         checkRadix(radix);
-        decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
 
-        String allAvailableDigits = "0123456789abcdefghijklmnopqrstuvwxyz";
-        String ASCIIDigit = allAvailableDigits.substring(0, radix);
-        String nonZeroASCIIDigit = allAvailableDigits.substring(1, radix);
+        if (decimalFormat == null) {
+            decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
+        }
 
-        StringBuilder digit = new StringBuilder("((?i)[").append(ASCIIDigit)
-                .append("]|\\p{javaDigit})");
-        StringBuilder nonZeroDigit = new StringBuilder("((?i)[").append(
-                nonZeroASCIIDigit).append("]|([\\p{javaDigit}&&[^0]]))");
-        StringBuilder numeral = getNumeral(digit, nonZeroDigit);
+        if (cachedIntegerPatternRadix == radix) {
+            return cachedIntegerPattern;
+        }
 
-        StringBuilder integer = new StringBuilder("(([-+]?(").append(numeral)
-                .append(")))|(").append(addPositiveSign(numeral)).append(")|(")
-                .append(addNegativeSign(numeral)).append(")");
+        String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+        String ASCIIDigit = digits.substring(0, radix);
+        String nonZeroASCIIDigit = digits.substring(1, radix);
 
-        Pattern integerPattern = Pattern.compile(integer.toString());
-        return integerPattern;
+        String digit = "((?i)[" + ASCIIDigit + "]|\\p{javaDigit})";
+        String nonZeroDigit = "((?i)[" + nonZeroASCIIDigit + "]|([\\p{javaDigit}&&[^0]]))";
+        String numeral = getNumeral(digit, nonZeroDigit);
+
+        String regex = "(([-+]?(" + numeral + ")))|" +
+            "(" + addPositiveSign(numeral) + ")|" +
+            "(" + addNegativeSign(numeral) + ")";
+
+        cachedIntegerPatternRadix = radix;
+        cachedIntegerPattern = Pattern.compile(regex);
+        return cachedIntegerPattern;
     }
 
-    /*
-     * Get pattern of float
-     */
     private Pattern getFloatPattern() {
-        decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
+        if (decimalFormat == null) {
+            decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
+        }
 
-        StringBuilder digit = new StringBuilder("([0-9]|(\\p{javaDigit}))");
-        StringBuilder nonZeroDigit = new StringBuilder("[\\p{javaDigit}&&[^0]]");
-        StringBuilder numeral = getNumeral(digit, nonZeroDigit);
+        if (cachedFloatPattern != null) {
+            return cachedFloatPattern;
+        }
 
-        String decimalSeparator = "\\" + decimalFormat.getDecimalFormatSymbols()
-                        .getDecimalSeparator();
-        StringBuilder decimalNumeral = new StringBuilder("(").append(numeral)
-                .append("|").append(numeral)
-                .append(decimalSeparator).append(digit).append("*+|").append(
-                        decimalSeparator).append(digit).append("++)");
-        StringBuilder exponent = new StringBuilder("([eE][+-]?").append(digit)
-                .append("+)?");
+        DecimalFormatSymbols dfs = decimalFormat.getDecimalFormatSymbols();
 
-        StringBuilder decimal = new StringBuilder("(([-+]?").append(
-                decimalNumeral).append("(").append(exponent).append("?)")
-                .append(")|(").append(addPositiveSign(decimalNumeral)).append(
-                        "(").append(exponent).append("?)").append(")|(")
-                .append(addNegativeSign(decimalNumeral)).append("(").append(
-                        exponent).append("?)").append("))");
+        String digit = "([0-9]|(\\p{javaDigit}))";
+        String nonZeroDigit = "[\\p{javaDigit}&&[^0]]";
+        String numeral = getNumeral(digit, nonZeroDigit);
 
-        StringBuilder hexFloat = new StringBuilder("([-+]?0[xX][0-9a-fA-F]*")
-                .append("\\.").append(
-                        "[0-9a-fA-F]+([pP][-+]?[0-9]+)?)");
-        String localNaN = decimalFormat.getDecimalFormatSymbols().getNaN();
-        String localeInfinity = decimalFormat.getDecimalFormatSymbols()
-                .getInfinity();
-        StringBuilder nonNumber = new StringBuilder("(NaN|\\Q").append(localNaN)
-                .append("\\E|Infinity|\\Q").append(localeInfinity).append("\\E)");
-        StringBuilder singedNonNumber = new StringBuilder("((([-+]?(").append(
-                nonNumber).append(")))|(").append(addPositiveSign(nonNumber))
-                .append(")|(").append(addNegativeSign(nonNumber)).append("))");
+        String decimalSeparator = "\\" + dfs.getDecimalSeparator();
+        String decimalNumeral = "(" + numeral + "|" +
+            numeral + decimalSeparator + digit + "*+|" +
+            decimalSeparator + digit + "++)";
+        String exponent = "([eE][+-]?" + digit + "+)?";
 
-        StringBuilder floatString = new StringBuilder().append(decimal).append(
-                "|").append(hexFloat).append("|").append(singedNonNumber);
-        Pattern floatPattern = Pattern.compile(floatString.toString());
-        return floatPattern;
+        String decimal = "(([-+]?" + decimalNumeral + "(" + exponent + "?)" + ")|" +
+            "(" + addPositiveSign(decimalNumeral) + "(" + exponent + "?)" + ")|" +
+            "(" + addNegativeSign(decimalNumeral) + "(" + exponent + "?)" + "))";
+
+        String hexFloat = "([-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?)";
+        String localNaN = dfs.getNaN();
+        String localeInfinity = dfs.getInfinity();
+        String nonNumber = "(NaN|\\Q" + localNaN + "\\E|Infinity|\\Q" + localeInfinity + "\\E)";
+        String signedNonNumber = "((([-+]?(" + nonNumber + ")))|" +
+            "(" + addPositiveSign(nonNumber) + ")|" +
+            "(" + addNegativeSign(nonNumber) + "))";
+
+        cachedFloatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" + signedNonNumber);
+        return cachedFloatPattern;
     }
 
-    private StringBuilder getNumeral(StringBuilder digit,
-            StringBuilder nonZeroDigit) {
-        String groupSeparator = "\\"
-                + decimalFormat.getDecimalFormatSymbols()
-                        .getGroupingSeparator();
-        StringBuilder groupedNumeral = new StringBuilder("(").append(
-                nonZeroDigit).append(digit).append("?").append(digit).append(
-                "?(").append(groupSeparator).append(digit).append(digit)
-                .append(digit).append(")+)");
-        StringBuilder numeral = new StringBuilder("((").append(digit).append(
-                "++)|").append(groupedNumeral).append(")");
-        return numeral;
+    private String getNumeral(String digit, String nonZeroDigit) {
+        String groupSeparator = "\\" + decimalFormat.getDecimalFormatSymbols().getGroupingSeparator();
+        String groupedNumeral = "(" + nonZeroDigit + digit + "?" + digit + "?" +
+            "(" + groupSeparator + digit + digit + digit + ")+)";
+        return "((" + digit + "++)|" + groupedNumeral + ")";
     }
 
     /*
      * Add the locale specific positive prefixes and suffixes to the pattern
      */
-    private StringBuilder addPositiveSign(StringBuilder unSignNumeral) {
+    private String addPositiveSign(String unsignedNumeral) {
         String positivePrefix = "";
         String positiveSuffix = "";
         if (!decimalFormat.getPositivePrefix().isEmpty()) {
@@ -1849,16 +1820,13 @@
         if (!decimalFormat.getPositiveSuffix().isEmpty()) {
             positiveSuffix = "\\Q" + decimalFormat.getPositiveSuffix() + "\\E";
         }
-        StringBuilder signedNumeral = new StringBuilder()
-                .append(positivePrefix).append(unSignNumeral).append(
-                        positiveSuffix);
-        return signedNumeral;
+        return positivePrefix + unsignedNumeral + positiveSuffix;
     }
 
     /*
      * Add the locale specific negative prefixes and suffixes to the pattern
      */
-    private StringBuilder addNegativeSign(StringBuilder unSignNumeral) {
+    private String addNegativeSign(String unsignedNumeral) {
         String negativePrefix = "";
         String negativeSuffix = "";
         if (!decimalFormat.getNegativePrefix().isEmpty()) {
@@ -1867,10 +1835,7 @@
         if (!decimalFormat.getNegativeSuffix().isEmpty()) {
             negativeSuffix = "\\Q" + decimalFormat.getNegativeSuffix() + "\\E";
         }
-        StringBuilder signedNumeral = new StringBuilder()
-                .append(negativePrefix).append(unSignNumeral).append(
-                        negativeSuffix);
-        return signedNumeral;
+        return negativePrefix + unsignedNumeral + negativeSuffix;
     }
 
     /*
@@ -1878,21 +1843,16 @@
      */
     private String removeLocaleInfoFromFloat(String floatString) {
         // If the token is HexFloat
-        if (-1 != floatString.indexOf('x') || -1 != floatString.indexOf('X')) {
+        if (floatString.indexOf('x') != -1 || floatString.indexOf('X') != -1) {
             return floatString;
         }
 
-        int exponentIndex;
-        String decimalNumeralString;
-        String exponentString;
         // If the token is scientific notation
-        if (-1 != (exponentIndex = floatString.indexOf('e'))
-                || -1 != (exponentIndex = floatString.indexOf('E'))) {
-            decimalNumeralString = floatString.substring(0, exponentIndex);
-            exponentString = floatString.substring(exponentIndex + 1,
-                    floatString.length());
-            decimalNumeralString = removeLocaleInfo(decimalNumeralString,
-                    DataType.FLOAT);
+        int exponentIndex;
+        if ((exponentIndex = floatString.indexOf('e')) != -1 || (exponentIndex = floatString.indexOf('E')) != -1) {
+            String decimalNumeralString = floatString.substring(0, exponentIndex);
+            String exponentString = floatString.substring(exponentIndex + 1, floatString.length());
+            decimalNumeralString = removeLocaleInfo(decimalNumeralString, DataType.FLOAT);
             return decimalNumeralString + "e" + exponentString;
         }
         return removeLocaleInfo(floatString, DataType.FLOAT);
@@ -1903,40 +1863,36 @@
      * specific suffixes from input string
      */
     private String removeLocaleInfo(String token, DataType type) {
+        DecimalFormatSymbols dfs = decimalFormat.getDecimalFormatSymbols();
+
         StringBuilder tokenBuilder = new StringBuilder(token);
         boolean negative = removeLocaleSign(tokenBuilder);
         // Remove group separator
-        String groupSeparator = String.valueOf(decimalFormat
-                .getDecimalFormatSymbols().getGroupingSeparator());
+        String groupSeparator = String.valueOf(dfs.getGroupingSeparator());
         int separatorIndex = -1;
-        while (-1 != (separatorIndex = tokenBuilder.indexOf(groupSeparator))) {
+        while ((separatorIndex = tokenBuilder.indexOf(groupSeparator)) != -1) {
             tokenBuilder.delete(separatorIndex, separatorIndex + 1);
         }
         // Remove decimal separator
-        String decimalSeparator = String.valueOf(decimalFormat
-                .getDecimalFormatSymbols().getDecimalSeparator());
+        String decimalSeparator = String.valueOf(dfs.getDecimalSeparator());
         separatorIndex = tokenBuilder.indexOf(decimalSeparator);
         StringBuilder result = new StringBuilder("");
         if (DataType.INT == type) {
             for (int i = 0; i < tokenBuilder.length(); i++) {
-                if (-1 != Character.digit(tokenBuilder.charAt(i),
-                        Character.MAX_RADIX)) {
+                if (Character.digit(tokenBuilder.charAt(i), Character.MAX_RADIX) != -1) {
                     result.append(tokenBuilder.charAt(i));
                 }
             }
         }
         if (DataType.FLOAT == type) {
-            if (tokenBuilder.toString().equals(
-                    decimalFormat.getDecimalFormatSymbols().getNaN())) {
+            if (tokenBuilder.toString().equals(dfs.getNaN())) {
                 result.append("NaN");
-            } else if (tokenBuilder.toString().equals(
-                    decimalFormat.getDecimalFormatSymbols().getInfinity())) {
+            } else if (tokenBuilder.toString().equals(dfs.getInfinity())) {
                 result.append("Infinity");
             } else {
                 for (int i = 0; i < tokenBuilder.length(); i++) {
-                    if (-1 != Character.digit(tokenBuilder.charAt(i), 10)) {
-                        result.append(Character.digit(tokenBuilder.charAt(i),
-                                10));
+                    if (Character.digit(tokenBuilder.charAt(i), 10) != -1) {
+                        result.append(Character.digit(tokenBuilder.charAt(i), 10));
                     }
                 }
             }
@@ -1945,7 +1901,7 @@
         if (result.length() == 0) {
             result = tokenBuilder;
         }
-        if (-1 != separatorIndex) {
+        if (separatorIndex != -1) {
             result.insert(separatorIndex, ".");
         }
         // If input is negative
@@ -1971,11 +1927,9 @@
         if (!positivePrefix.isEmpty() && tokenBuilder.indexOf(positivePrefix) == 0) {
             tokenBuilder.delete(0, positivePrefix.length());
         }
-        if (!positiveSuffix.isEmpty()
-                && -1 != tokenBuilder.indexOf(positiveSuffix)) {
-            tokenBuilder.delete(
-                    tokenBuilder.length() - positiveSuffix.length(),
-                    tokenBuilder.length());
+        if (!positiveSuffix.isEmpty() && tokenBuilder.indexOf(positiveSuffix) != -1) {
+            tokenBuilder.delete(tokenBuilder.length() - positiveSuffix.length(),
+                                tokenBuilder.length());
         }
         boolean negative = false;
         if (tokenBuilder.indexOf("-") == 0) {
@@ -1986,19 +1940,17 @@
             tokenBuilder.delete(0, negativePrefix.length());
             negative = true;
         }
-        if (!negativeSuffix.isEmpty()
-                && -1 != tokenBuilder.indexOf(negativeSuffix)) {
-            tokenBuilder.delete(
-                    tokenBuilder.length() - negativeSuffix.length(),
-                    tokenBuilder.length());
+        if (!negativeSuffix.isEmpty() && tokenBuilder.indexOf(negativeSuffix) != -1) {
+            tokenBuilder.delete(tokenBuilder.length() - negativeSuffix.length(),
+                                tokenBuilder.length());
             negative = true;
         }
         return negative;
     }
 
     /*
-     * Find the prefixed delimiter and posefixed delimiter in the input resource
-     * and set the start index and end index of Matcher region. If postfixed
+     * Find the prefixed delimiter and suffixed delimiter in the input resource
+     * and set the start index and end index of Matcher region. If the suffixed
      * delimiter does not exist, the end index is set to be end of input.
      */
     private boolean setTokenRegion() {
@@ -2014,7 +1966,7 @@
         if (setHeadTokenRegion(tokenStartIndex)) {
             return true;
         }
-        tokenEndIndex = findPostDelimiter();
+        tokenEndIndex = findDelimiterAfter();
         // If the second delimiter is not found
         if (-1 == tokenEndIndex) {
             // Just first Delimiter Exists
@@ -2069,7 +2021,7 @@
         int tokenStartIndex;
         int tokenEndIndex;
         boolean setSuccess = false;
-        // If no delimiter exists, but something exites in this scanner
+        // If no delimiter exists, but something exists in this scanner
         if (-1 == findIndex && preStartIndex != bufferLength) {
             tokenStartIndex = preStartIndex;
             tokenEndIndex = bufferLength;
@@ -2089,17 +2041,13 @@
         return setSuccess;
     }
 
-    /*
-     * Find postfix delimiter
-     */
-    private int findPostDelimiter() {
+    private int findDelimiterAfter() {
         int tokenEndIndex = 0;
         boolean findComplete = false;
         while (!findComplete) {
             if (matcher.find()) {
                 findComplete = true;
-                if (matcher.start() == findStartIndex
-                        && matcher.start() == matcher.end()) {
+                if (matcher.start() == findStartIndex && matcher.start() == matcher.end()) {
                     findComplete = false;
                 }
             } else {
@@ -2165,7 +2113,7 @@
         int oldPosition = buffer.position();
         int oldCapacity = buffer.capacity();
         int oldLimit = buffer.limit();
-        int newCapacity = oldCapacity * DIPLOID;
+        int newCapacity = oldCapacity * 2;
         char[] newBuffer = new char[newCapacity];
         System.arraycopy(buffer.array(), 0, newBuffer, 0, oldLimit);
         buffer = CharBuffer.wrap(newBuffer, 0, newCapacity);
@@ -2181,8 +2129,8 @@
      */
     public Scanner reset() {
         delimiter = DEFAULT_DELIMITER;
-        locale = Locale.getDefault();
-        integerRadix = 10;
+        setLocale(Locale.getDefault());
+        currentRadix = DEFAULT_RADIX;
         return this;
     }
 }
diff --git a/luni/src/main/java/java/util/SortedMap.java b/luni/src/main/java/java/util/SortedMap.java
index aec7adf..63acafd 100644
--- a/luni/src/main/java/java/util/SortedMap.java
+++ b/luni/src/main/java/java/util/SortedMap.java
@@ -25,16 +25,14 @@
 public interface SortedMap<K,V> extends Map<K,V> {
 
     /**
-     * Returns the comparator used to compare keys in this sorted map.
-     *
-     * @return the comparator or {@code null} if the natural order is used.
+     * Returns the comparator used to compare keys in this sorted map, or null if the natural
+     * ordering is in use.
      */
     public Comparator<? super K> comparator();
 
     /**
-     * Returns the first key in this sorted map.
+     * Returns the least key in this sorted map.
      *
-     * @return the first key in this sorted map.
      * @throws NoSuchElementException
      *                if this sorted map is empty.
      */
@@ -64,9 +62,8 @@
     public SortedMap<K,V> headMap(K endKey);
 
     /**
-     * Returns the last key in this sorted map.
+     * Returns the greatest key in this sorted map.
      *
-     * @return the last key in this sorted map.
      * @throws NoSuchElementException
      *                if this sorted map is empty.
      */
diff --git a/luni/src/main/java/java/util/TimeZone.java b/luni/src/main/java/java/util/TimeZone.java
index 848ebbb..c024e8d 100644
--- a/luni/src/main/java/java/util/TimeZone.java
+++ b/luni/src/main/java/java/util/TimeZone.java
@@ -22,8 +22,12 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import libcore.icu.TimeZoneNames;
+import libcore.io.IoUtils;
 import libcore.util.ZoneInfoDB;
 
+// TODO: repackage this class, used by frameworks/base.
+import org.apache.harmony.luni.internal.util.TimezoneGetter;
+
 /**
  * {@code TimeZone} represents a time zone, primarily used for configuring a {@link Calendar} or
  * {@link java.text.SimpleDateFormat} instance.
@@ -105,7 +109,7 @@
      * instance.
      */
     public static synchronized String[] getAvailableIDs() {
-        return ZoneInfoDB.getAvailableIDs();
+        return ZoneInfoDB.getInstance().getAvailableIDs();
     }
 
     /**
@@ -116,7 +120,7 @@
      * @return a possibly-empty array.
      */
     public static synchronized String[] getAvailableIDs(int offsetMillis) {
-        return ZoneInfoDB.getAvailableIDs(offsetMillis);
+        return ZoneInfoDB.getInstance().getAvailableIDs(offsetMillis);
     }
 
     /**
@@ -128,7 +132,22 @@
      */
     public static synchronized TimeZone getDefault() {
         if (defaultTimeZone == null) {
-            defaultTimeZone = ZoneInfoDB.getSystemDefault();
+            TimezoneGetter tzGetter = TimezoneGetter.getInstance();
+            String zoneName = (tzGetter != null) ? tzGetter.getId() : null;
+            if (zoneName != null) {
+                zoneName = zoneName.trim();
+            }
+            if (zoneName == null || zoneName.isEmpty()) {
+                try {
+                    // On the host, we can find the configured timezone here.
+                    zoneName = IoUtils.readFileAsString("/etc/timezone");
+                } catch (IOException ex) {
+                    // "vogar --mode device" can end up here.
+                    // TODO: give libcore access to Android system properties and read "persist.sys.timezone".
+                    zoneName = "GMT";
+                }
+            }
+            defaultTimeZone = TimeZone.getTimeZone(zoneName);
         }
         return (TimeZone) defaultTimeZone.clone();
     }
@@ -323,7 +342,7 @@
         // In the database?
         TimeZone zone = null;
         try {
-            zone = ZoneInfoDB.makeTimeZone(id);
+            zone = ZoneInfoDB.getInstance().makeTimeZone(id);
         } catch (IOException ignored) {
         }
 
diff --git a/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java b/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
index a7f7745..23e68bb 100644
--- a/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
@@ -9,19 +9,19 @@
 
 /**
  * Provides default implementations of {@link ExecutorService}
- * execution methods. This class implements the <tt>submit</tt>,
- * <tt>invokeAny</tt> and <tt>invokeAll</tt> methods using a
- * {@link RunnableFuture} returned by <tt>newTaskFor</tt>, which defaults
+ * execution methods. This class implements the {@code submit},
+ * {@code invokeAny} and {@code invokeAll} methods using a
+ * {@link RunnableFuture} returned by {@code newTaskFor}, which defaults
  * to the {@link FutureTask} class provided in this package.  For example,
- * the implementation of <tt>submit(Runnable)</tt> creates an
- * associated <tt>RunnableFuture</tt> that is executed and
- * returned. Subclasses may override the <tt>newTaskFor</tt> methods
- * to return <tt>RunnableFuture</tt> implementations other than
- * <tt>FutureTask</tt>.
+ * the implementation of {@code submit(Runnable)} creates an
+ * associated {@code RunnableFuture} that is executed and
+ * returned. Subclasses may override the {@code newTaskFor} methods
+ * to return {@code RunnableFuture} implementations other than
+ * {@code FutureTask}.
  *
- * <p> <b>Extension example</b>. Here is a sketch of a class
+ * <p><b>Extension example</b>. Here is a sketch of a class
  * that customizes {@link ThreadPoolExecutor} to use
- * a <tt>CustomTask</tt> class instead of the default <tt>FutureTask</tt>:
+ * a {@code CustomTask} class instead of the default {@code FutureTask}:
  *  <pre> {@code
  * public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
  *
@@ -42,15 +42,15 @@
 public abstract class AbstractExecutorService implements ExecutorService {
 
     /**
-     * Returns a <tt>RunnableFuture</tt> for the given runnable and default
+     * Returns a {@code RunnableFuture} for the given runnable and default
      * value.
      *
      * @param runnable the runnable task being wrapped
      * @param value the default value for the returned future
-     * @return a <tt>RunnableFuture</tt> which when run will run the
-     * underlying runnable and which, as a <tt>Future</tt>, will yield
+     * @return a {@code RunnableFuture} which, when run, will run the
+     * underlying runnable and which, as a {@code Future}, will yield
      * the given value as its result and provide for cancellation of
-     * the underlying task.
+     * the underlying task
      * @since 1.6
      */
     protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
@@ -58,13 +58,13 @@
     }
 
     /**
-     * Returns a <tt>RunnableFuture</tt> for the given callable task.
+     * Returns a {@code RunnableFuture} for the given callable task.
      *
      * @param callable the callable task being wrapped
-     * @return a <tt>RunnableFuture</tt> which when run will call the
-     * underlying callable and which, as a <tt>Future</tt>, will yield
+     * @return a {@code RunnableFuture} which, when run, will call the
+     * underlying callable and which, as a {@code Future}, will yield
      * the callable's result as its result and provide for
-     * cancellation of the underlying task.
+     * cancellation of the underlying task
      * @since 1.6
      */
     protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
@@ -108,14 +108,14 @@
      * the main mechanics of invokeAny.
      */
     private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
-                            boolean timed, long nanos)
+                              boolean timed, long nanos)
         throws InterruptedException, ExecutionException, TimeoutException {
         if (tasks == null)
             throw new NullPointerException();
         int ntasks = tasks.size();
         if (ntasks == 0)
             throw new IllegalArgumentException();
-        List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
+        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
         ExecutorCompletionService<T> ecs =
             new ExecutorCompletionService<T>(this);
 
@@ -129,7 +129,7 @@
             // Record exceptions so that if we fail to obtain any
             // result, we can throw the last exception we got.
             ExecutionException ee = null;
-            long lastTime = timed ? System.nanoTime() : 0;
+            final long deadline = timed ? System.nanoTime() + nanos : 0L;
             Iterator<? extends Callable<T>> it = tasks.iterator();
 
             // Start one task for sure; the rest incrementally
@@ -151,9 +151,7 @@
                         f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
                         if (f == null)
                             throw new TimeoutException();
-                        long now = System.nanoTime();
-                        nanos -= now - lastTime;
-                        lastTime = now;
+                        nanos = deadline - System.nanoTime();
                     }
                     else
                         f = ecs.take();
@@ -175,8 +173,8 @@
             throw ee;
 
         } finally {
-            for (Future<T> f : futures)
-                f.cancel(true);
+            for (int i = 0, size = futures.size(); i < size; i++)
+                futures.get(i).cancel(true);
         }
     }
 
@@ -200,7 +198,7 @@
         throws InterruptedException {
         if (tasks == null)
             throw new NullPointerException();
-        List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
         boolean done = false;
         try {
             for (Callable<T> t : tasks) {
@@ -208,7 +206,8 @@
                 futures.add(f);
                 execute(f);
             }
-            for (Future<T> f : futures) {
+            for (int i = 0, size = futures.size(); i < size; i++) {
+                Future<T> f = futures.get(i);
                 if (!f.isDone()) {
                     try {
                         f.get();
@@ -221,40 +220,39 @@
             return futures;
         } finally {
             if (!done)
-                for (Future<T> f : futures)
-                    f.cancel(true);
+                for (int i = 0, size = futures.size(); i < size; i++)
+                    futures.get(i).cancel(true);
         }
     }
 
     public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                          long timeout, TimeUnit unit)
         throws InterruptedException {
-        if (tasks == null || unit == null)
+        if (tasks == null)
             throw new NullPointerException();
         long nanos = unit.toNanos(timeout);
-        List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
         boolean done = false;
         try {
             for (Callable<T> t : tasks)
                 futures.add(newTaskFor(t));
 
-            long lastTime = System.nanoTime();
+            final long deadline = System.nanoTime() + nanos;
+            final int size = futures.size();
 
             // Interleave time checks and calls to execute in case
             // executor doesn't have any/much parallelism.
-            Iterator<Future<T>> it = futures.iterator();
-            while (it.hasNext()) {
-                execute((Runnable)(it.next()));
-                long now = System.nanoTime();
-                nanos -= now - lastTime;
-                lastTime = now;
-                if (nanos <= 0)
+            for (int i = 0; i < size; i++) {
+                execute((Runnable)futures.get(i));
+                nanos = deadline - System.nanoTime();
+                if (nanos <= 0L)
                     return futures;
             }
 
-            for (Future<T> f : futures) {
+            for (int i = 0; i < size; i++) {
+                Future<T> f = futures.get(i);
                 if (!f.isDone()) {
-                    if (nanos <= 0)
+                    if (nanos <= 0L)
                         return futures;
                     try {
                         f.get(nanos, TimeUnit.NANOSECONDS);
@@ -263,17 +261,15 @@
                     } catch (TimeoutException toe) {
                         return futures;
                     }
-                    long now = System.nanoTime();
-                    nanos -= now - lastTime;
-                    lastTime = now;
+                    nanos = deadline - System.nanoTime();
                 }
             }
             done = true;
             return futures;
         } finally {
             if (!done)
-                for (Future<T> f : futures)
-                    f.cancel(true);
+                for (int i = 0, size = futures.size(); i < size; i++)
+                    futures.get(i).cancel(true);
         }
     }
 
diff --git a/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java b/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
index e30ab67..3cfe6d5 100644
--- a/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
@@ -111,9 +111,9 @@
     /**
      * Returns item at index i.
      */
+    @SuppressWarnings("unchecked")
     final E itemAt(int i) {
-        @SuppressWarnings("unchecked") E x = (E) items[i];
-        return x;
+        return (E) items[i];
     }
 
     /**
@@ -147,7 +147,8 @@
         // assert lock.getHoldCount() == 1;
         // assert items[takeIndex] != null;
         final Object[] items = this.items;
-        @SuppressWarnings("unchecked") E x = (E) items[takeIndex];
+        @SuppressWarnings("unchecked")
+        E x = (E) items[takeIndex];
         items[takeIndex] = null;
         takeIndex = inc(takeIndex);
         count--;
@@ -396,7 +397,7 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            return (count == 0) ? null : itemAt(takeIndex);
+            return itemAt(takeIndex); // null when queue is empty
         } finally {
             lock.unlock();
         }
@@ -529,8 +530,13 @@
         try {
             final int count = this.count;
             Object[] a = new Object[count];
-            for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
-                a[k] = items[i];
+            int n = items.length - takeIndex;
+            if (count <= n) {
+                System.arraycopy(items, takeIndex, a, 0, count);
+            } else {
+                System.arraycopy(items, takeIndex, a, 0, n);
+                System.arraycopy(items, 0, a, n, count - n);
+            }
             return a;
         } finally {
             lock.unlock();
@@ -583,8 +589,13 @@
             if (len < count)
                 a = (T[])java.lang.reflect.Array.newInstance(
                     a.getClass().getComponentType(), count);
-            for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
-                a[k] = (T) items[i];
+            int n = items.length - takeIndex;
+            if (count <= n)
+                System.arraycopy(items, takeIndex, a, 0, count);
+            else {
+                System.arraycopy(items, takeIndex, a, 0, n);
+                System.arraycopy(items, 0, a, n, count - n);
+            }
             if (len > count)
                 a[count] = null;
             return a;
@@ -674,7 +685,8 @@
             int i = 0;
             try {
                 while (i < n) {
-                    @SuppressWarnings("unchecked") E x = (E) items[take];
+                    @SuppressWarnings("unchecked")
+                    E x = (E) items[take];
                     c.add(x);
                     items[take] = null;
                     take = inc(take);
diff --git a/luni/src/main/java/java/util/concurrent/BlockingDeque.java b/luni/src/main/java/java/util/concurrent/BlockingDeque.java
index 34f103d..8a393ba 100644
--- a/luni/src/main/java/java/util/concurrent/BlockingDeque.java
+++ b/luni/src/main/java/java/util/concurrent/BlockingDeque.java
@@ -12,11 +12,11 @@
  * for the deque to become non-empty when retrieving an element, and wait for
  * space to become available in the deque when storing an element.
  *
- * <p><tt>BlockingDeque</tt> methods come in four forms, with different ways
+ * <p>{@code BlockingDeque} methods come in four forms, with different ways
  * of handling operations that cannot be satisfied immediately, but may be
  * satisfied at some point in the future:
  * one throws an exception, the second returns a special value (either
- * <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
+ * {@code null} or {@code false}, depending on the operation), the third
  * blocks the current thread indefinitely until the operation can succeed,
  * and the fourth blocks for only a given maximum time limit before giving
  * up.  These methods are summarized in the following table:
@@ -87,20 +87,20 @@
  *  </tr>
  * </table>
  *
- * <p>Like any {@link BlockingQueue}, a <tt>BlockingDeque</tt> is thread safe,
+ * <p>Like any {@link BlockingQueue}, a {@code BlockingDeque} is thread safe,
  * does not permit null elements, and may (or may not) be
  * capacity-constrained.
  *
- * <p>A <tt>BlockingDeque</tt> implementation may be used directly as a FIFO
- * <tt>BlockingQueue</tt>. The methods inherited from the
- * <tt>BlockingQueue</tt> interface are precisely equivalent to
- * <tt>BlockingDeque</tt> methods as indicated in the following table:
+ * <p>A {@code BlockingDeque} implementation may be used directly as a FIFO
+ * {@code BlockingQueue}. The methods inherited from the
+ * {@code BlockingQueue} interface are precisely equivalent to
+ * {@code BlockingDeque} methods as indicated in the following table:
  *
  * <p>
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
  *  <tr>
- *    <td ALIGN=CENTER> <b><tt>BlockingQueue</tt> Method</b></td>
- *    <td ALIGN=CENTER> <b>Equivalent <tt>BlockingDeque</tt> Method</b></td>
+ *    <td ALIGN=CENTER> <b>{@code BlockingQueue} Method</b></td>
+ *    <td ALIGN=CENTER> <b>Equivalent {@code BlockingDeque} Method</b></td>
  *  </tr>
  *  <tr>
  *    <td ALIGN=CENTER COLSPAN = 2> <b>Insert</b></td>
@@ -179,7 +179,7 @@
     /**
      * Inserts the specified element at the front of this deque if it is
      * possible to do so immediately without violating capacity restrictions,
-     * throwing an <tt>IllegalStateException</tt> if no space is currently
+     * throwing an {@code IllegalStateException} if no space is currently
      * available.  When using a capacity-restricted deque, it is generally
      * preferable to use {@link #offerFirst(Object) offerFirst}.
      *
@@ -194,7 +194,7 @@
     /**
      * Inserts the specified element at the end of this deque if it is
      * possible to do so immediately without violating capacity restrictions,
-     * throwing an <tt>IllegalStateException</tt> if no space is currently
+     * throwing an {@code IllegalStateException} if no space is currently
      * available.  When using a capacity-restricted deque, it is generally
      * preferable to use {@link #offerLast(Object) offerLast}.
      *
@@ -209,7 +209,7 @@
     /**
      * Inserts the specified element at the front of this deque if it is
      * possible to do so immediately without violating capacity restrictions,
-     * returning <tt>true</tt> upon success and <tt>false</tt> if no space is
+     * returning {@code true} upon success and {@code false} if no space is
      * currently available.
      * When using a capacity-restricted deque, this method is generally
      * preferable to the {@link #addFirst(Object) addFirst} method, which can
@@ -225,7 +225,7 @@
     /**
      * Inserts the specified element at the end of this deque if it is
      * possible to do so immediately without violating capacity restrictions,
-     * returning <tt>true</tt> upon success and <tt>false</tt> if no space is
+     * returning {@code true} upon success and {@code false} if no space is
      * currently available.
      * When using a capacity-restricted deque, this method is generally
      * preferable to the {@link #addLast(Object) addLast} method, which can
@@ -273,10 +273,10 @@
      *
      * @param e the element to add
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return {@code true} if successful, or {@code false} if
      *         the specified waiting time elapses before space is available
      * @throws InterruptedException if interrupted while waiting
      * @throws ClassCastException if the class of the specified element
@@ -295,10 +295,10 @@
      *
      * @param e the element to add
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return {@code true} if successful, or {@code false} if
      *         the specified waiting time elapses before space is available
      * @throws InterruptedException if interrupted while waiting
      * @throws ClassCastException if the class of the specified element
@@ -334,10 +334,10 @@
      * become available.
      *
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return the head of this deque, or <tt>null</tt> if the specified
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return the head of this deque, or {@code null} if the specified
      *         waiting time elapses before an element is available
      * @throws InterruptedException if interrupted while waiting
      */
@@ -350,10 +350,10 @@
      * become available.
      *
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return the tail of this deque, or <tt>null</tt> if the specified
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return the tail of this deque, or {@code null} if the specified
      *         waiting time elapses before an element is available
      * @throws InterruptedException if interrupted while waiting
      */
@@ -363,13 +363,13 @@
     /**
      * Removes the first occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
-     * More formally, removes the first element <tt>e</tt> such that
-     * <tt>o.equals(e)</tt> (if such an element exists).
-     * Returns <tt>true</tt> if this deque contained the specified element
+     * More formally, removes the first element {@code e} such that
+     * {@code o.equals(e)} (if such an element exists).
+     * Returns {@code true} if this deque contained the specified element
      * (or equivalently, if this deque changed as a result of the call).
      *
      * @param o element to be removed from this deque, if present
-     * @return <tt>true</tt> if an element was removed as a result of this call
+     * @return {@code true} if an element was removed as a result of this call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -381,13 +381,13 @@
     /**
      * Removes the last occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
-     * More formally, removes the last element <tt>e</tt> such that
-     * <tt>o.equals(e)</tt> (if such an element exists).
-     * Returns <tt>true</tt> if this deque contained the specified element
+     * More formally, removes the last element {@code e} such that
+     * {@code o.equals(e)} (if such an element exists).
+     * Returns {@code true} if this deque contained the specified element
      * (or equivalently, if this deque changed as a result of the call).
      *
      * @param o element to be removed from this deque, if present
-     * @return <tt>true</tt> if an element was removed as a result of this call
+     * @return {@code true} if an element was removed as a result of this call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -402,8 +402,8 @@
      * Inserts the specified element into the queue represented by this deque
      * (in other words, at the tail of this deque) if it is possible to do so
      * immediately without violating capacity restrictions, returning
-     * <tt>true</tt> upon success and throwing an
-     * <tt>IllegalStateException</tt> if no space is currently available.
+     * {@code true} upon success and throwing an
+     * {@code IllegalStateException} if no space is currently available.
      * When using a capacity-restricted deque, it is generally preferable to
      * use {@link #offer(Object) offer}.
      *
@@ -423,7 +423,7 @@
      * Inserts the specified element into the queue represented by this deque
      * (in other words, at the tail of this deque) if it is possible to do so
      * immediately without violating capacity restrictions, returning
-     * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+     * {@code true} upon success and {@code false} if no space is currently
      * available.  When using a capacity-restricted deque, this method is
      * generally preferable to the {@link #add} method, which can fail to
      * insert an element only by throwing an exception.
@@ -465,8 +465,8 @@
      * {@link #offerLast(Object,long,TimeUnit) offerLast}.
      *
      * @param e the element to add
-     * @return <tt>true</tt> if the element was added to this deque, else
-     *         <tt>false</tt>
+     * @return {@code true} if the element was added to this deque, else
+     *         {@code false}
      * @throws InterruptedException {@inheritDoc}
      * @throws ClassCastException if the class of the specified element
      *         prevents it from being added to this deque
@@ -493,11 +493,11 @@
     /**
      * Retrieves and removes the head of the queue represented by this deque
      * (in other words, the first element of this deque), or returns
-     * <tt>null</tt> if this deque is empty.
+     * {@code null} if this deque is empty.
      *
      * <p>This method is equivalent to {@link #pollFirst()}.
      *
-     * @return the head of this deque, or <tt>null</tt> if this deque is empty
+     * @return the head of this deque, or {@code null} if this deque is empty
      */
     E poll();
 
@@ -521,7 +521,7 @@
      * <p>This method is equivalent to
      * {@link #pollFirst(long,TimeUnit) pollFirst}.
      *
-     * @return the head of this deque, or <tt>null</tt> if the
+     * @return the head of this deque, or {@code null} if the
      *         specified waiting time elapses before an element is available
      * @throws InterruptedException if interrupted while waiting
      */
@@ -544,27 +544,27 @@
     /**
      * Retrieves, but does not remove, the head of the queue represented by
      * this deque (in other words, the first element of this deque), or
-     * returns <tt>null</tt> if this deque is empty.
+     * returns {@code null} if this deque is empty.
      *
      * <p>This method is equivalent to {@link #peekFirst() peekFirst}.
      *
-     * @return the head of this deque, or <tt>null</tt> if this deque is empty
+     * @return the head of this deque, or {@code null} if this deque is empty
      */
     E peek();
 
     /**
      * Removes the first occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
-     * More formally, removes the first element <tt>e</tt> such that
-     * <tt>o.equals(e)</tt> (if such an element exists).
-     * Returns <tt>true</tt> if this deque contained the specified element
+     * More formally, removes the first element {@code e} such that
+     * {@code o.equals(e)} (if such an element exists).
+     * Returns {@code true} if this deque contained the specified element
      * (or equivalently, if this deque changed as a result of the call).
      *
      * <p>This method is equivalent to
      * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
      *
      * @param o element to be removed from this deque, if present
-     * @return <tt>true</tt> if this deque changed as a result of the call
+     * @return {@code true} if this deque changed as a result of the call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -574,12 +574,12 @@
     boolean remove(Object o);
 
     /**
-     * Returns <tt>true</tt> if this deque contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this deque contains
-     * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+     * Returns {@code true} if this deque contains the specified element.
+     * More formally, returns {@code true} if and only if this deque contains
+     * at least one element {@code e} such that {@code o.equals(e)}.
      *
      * @param o object to be checked for containment in this deque
-     * @return <tt>true</tt> if this deque contains the specified element
+     * @return {@code true} if this deque contains the specified element
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this deque
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
diff --git a/luni/src/main/java/java/util/concurrent/BlockingQueue.java b/luni/src/main/java/java/util/concurrent/BlockingQueue.java
index 6cfe52b..cc6d541 100644
--- a/luni/src/main/java/java/util/concurrent/BlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/BlockingQueue.java
@@ -19,11 +19,11 @@
  * element, and wait for space to become available in the queue when
  * storing an element.
  *
- * <p><tt>BlockingQueue</tt> methods come in four forms, with different ways
+ * <p>{@code BlockingQueue} methods come in four forms, with different ways
  * of handling operations that cannot be satisfied immediately, but may be
  * satisfied at some point in the future:
  * one throws an exception, the second returns a special value (either
- * <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
+ * {@code null} or {@code false}, depending on the operation), the third
  * blocks the current thread indefinitely until the operation can succeed,
  * and the fourth blocks for only a given maximum time limit before giving
  * up.  These methods are summarized in the following table:
@@ -60,37 +60,37 @@
  *  </tr>
  * </table>
  *
- * <p>A <tt>BlockingQueue</tt> does not accept <tt>null</tt> elements.
- * Implementations throw <tt>NullPointerException</tt> on attempts
- * to <tt>add</tt>, <tt>put</tt> or <tt>offer</tt> a <tt>null</tt>.  A
- * <tt>null</tt> is used as a sentinel value to indicate failure of
- * <tt>poll</tt> operations.
+ * <p>A {@code BlockingQueue} does not accept {@code null} elements.
+ * Implementations throw {@code NullPointerException} on attempts
+ * to {@code add}, {@code put} or {@code offer} a {@code null}.  A
+ * {@code null} is used as a sentinel value to indicate failure of
+ * {@code poll} operations.
  *
- * <p>A <tt>BlockingQueue</tt> may be capacity bounded. At any given
- * time it may have a <tt>remainingCapacity</tt> beyond which no
- * additional elements can be <tt>put</tt> without blocking.
- * A <tt>BlockingQueue</tt> without any intrinsic capacity constraints always
- * reports a remaining capacity of <tt>Integer.MAX_VALUE</tt>.
+ * <p>A {@code BlockingQueue} may be capacity bounded. At any given
+ * time it may have a {@code remainingCapacity} beyond which no
+ * additional elements can be {@code put} without blocking.
+ * A {@code BlockingQueue} without any intrinsic capacity constraints always
+ * reports a remaining capacity of {@code Integer.MAX_VALUE}.
  *
- * <p> <tt>BlockingQueue</tt> implementations are designed to be used
+ * <p>{@code BlockingQueue} implementations are designed to be used
  * primarily for producer-consumer queues, but additionally support
  * the {@link java.util.Collection} interface.  So, for example, it is
  * possible to remove an arbitrary element from a queue using
- * <tt>remove(x)</tt>. However, such operations are in general
+ * {@code remove(x)}. However, such operations are in general
  * <em>not</em> performed very efficiently, and are intended for only
  * occasional use, such as when a queued message is cancelled.
  *
- * <p> <tt>BlockingQueue</tt> implementations are thread-safe.  All
+ * <p>{@code BlockingQueue} implementations are thread-safe.  All
  * queuing methods achieve their effects atomically using internal
  * locks or other forms of concurrency control. However, the
- * <em>bulk</em> Collection operations <tt>addAll</tt>,
- * <tt>containsAll</tt>, <tt>retainAll</tt> and <tt>removeAll</tt> are
+ * <em>bulk</em> Collection operations {@code addAll},
+ * {@code containsAll}, {@code retainAll} and {@code removeAll} are
  * <em>not</em> necessarily performed atomically unless specified
  * otherwise in an implementation. So it is possible, for example, for
- * <tt>addAll(c)</tt> to fail (throwing an exception) after adding
- * only some of the elements in <tt>c</tt>.
+ * {@code addAll(c)} to fail (throwing an exception) after adding
+ * only some of the elements in {@code c}.
  *
- * <p>A <tt>BlockingQueue</tt> does <em>not</em> intrinsically support
+ * <p>A {@code BlockingQueue} does <em>not</em> intrinsically support
  * any kind of &quot;close&quot; or &quot;shutdown&quot; operation to
  * indicate that no more items will be added.  The needs and usage of
  * such features tend to be implementation-dependent. For example, a
@@ -100,7 +100,7 @@
  *
  * <p>
  * Usage example, based on a typical producer-consumer scenario.
- * Note that a <tt>BlockingQueue</tt> can safely be used with multiple
+ * Note that a {@code BlockingQueue} can safely be used with multiple
  * producers and multiple consumers.
  *  <pre> {@code
  * class Producer implements Runnable {
@@ -152,13 +152,13 @@
     /**
      * Inserts the specified element into this queue if it is possible to do
      * so immediately without violating capacity restrictions, returning
-     * <tt>true</tt> upon success and throwing an
-     * <tt>IllegalStateException</tt> if no space is currently available.
+     * {@code true} upon success and throwing an
+     * {@code IllegalStateException} if no space is currently available.
      * When using a capacity-restricted queue, it is generally preferable to
      * use {@link #offer(Object) offer}.
      *
      * @param e the element to add
-     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @return {@code true} (as specified by {@link Collection#add})
      * @throws IllegalStateException if the element cannot be added at this
      *         time due to capacity restrictions
      * @throws ClassCastException if the class of the specified element
@@ -172,14 +172,14 @@
     /**
      * Inserts the specified element into this queue if it is possible to do
      * so immediately without violating capacity restrictions, returning
-     * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+     * {@code true} upon success and {@code false} if no space is currently
      * available.  When using a capacity-restricted queue, this method is
      * generally preferable to {@link #add}, which can fail to insert an
      * element only by throwing an exception.
      *
      * @param e the element to add
-     * @return <tt>true</tt> if the element was added to this queue, else
-     *         <tt>false</tt>
+     * @return {@code true} if the element was added to this queue, else
+     *         {@code false}
      * @throws ClassCastException if the class of the specified element
      *         prevents it from being added to this queue
      * @throws NullPointerException if the specified element is null
@@ -208,10 +208,10 @@
      *
      * @param e the element to add
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return {@code true} if successful, or {@code false} if
      *         the specified waiting time elapses before space is available
      * @throws InterruptedException if interrupted while waiting
      * @throws ClassCastException if the class of the specified element
@@ -237,10 +237,10 @@
      * specified wait time if necessary for an element to become available.
      *
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
-     * @return the head of this queue, or <tt>null</tt> if the
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
+     * @return the head of this queue, or {@code null} if the
      *         specified waiting time elapses before an element is available
      * @throws InterruptedException if interrupted while waiting
      */
@@ -250,11 +250,11 @@
     /**
      * Returns the number of additional elements that this queue can ideally
      * (in the absence of memory or resource constraints) accept without
-     * blocking, or <tt>Integer.MAX_VALUE</tt> if there is no intrinsic
+     * blocking, or {@code Integer.MAX_VALUE} if there is no intrinsic
      * limit.
      *
      * <p>Note that you <em>cannot</em> always tell if an attempt to insert
-     * an element will succeed by inspecting <tt>remainingCapacity</tt>
+     * an element will succeed by inspecting {@code remainingCapacity}
      * because it may be the case that another thread is about to
      * insert or remove an element.
      *
@@ -264,14 +264,14 @@
 
     /**
      * Removes a single instance of the specified element from this queue,
-     * if it is present.  More formally, removes an element <tt>e</tt> such
-     * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+     * if it is present.  More formally, removes an element {@code e} such
+     * that {@code o.equals(e)}, if this queue contains one or more such
      * elements.
-     * Returns <tt>true</tt> if this queue contained the specified element
+     * Returns {@code true} if this queue contained the specified element
      * (or equivalently, if this queue changed as a result of the call).
      *
      * @param o element to be removed from this queue, if present
-     * @return <tt>true</tt> if this queue changed as a result of the call
+     * @return {@code true} if this queue changed as a result of the call
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this queue
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -281,12 +281,12 @@
     boolean remove(Object o);
 
     /**
-     * Returns <tt>true</tt> if this queue contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this queue contains
-     * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+     * Returns {@code true} if this queue contains the specified element.
+     * More formally, returns {@code true} if and only if this queue contains
+     * at least one element {@code e} such that {@code o.equals(e)}.
      *
      * @param o object to be checked for containment in this queue
-     * @return <tt>true</tt> if this queue contains the specified element
+     * @return {@code true} if this queue contains the specified element
      * @throws ClassCastException if the class of the specified element
      *         is incompatible with this queue
      *         (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -300,10 +300,10 @@
      * to the given collection.  This operation may be more
      * efficient than repeatedly polling this queue.  A failure
      * encountered while attempting to add elements to
-     * collection <tt>c</tt> may result in elements being in neither,
+     * collection {@code c} may result in elements being in neither,
      * either or both collections when the associated exception is
      * thrown.  Attempts to drain a queue to itself result in
-     * <tt>IllegalArgumentException</tt>. Further, the behavior of
+     * {@code IllegalArgumentException}. Further, the behavior of
      * this operation is undefined if the specified collection is
      * modified while the operation is in progress.
      *
@@ -324,10 +324,10 @@
      * Removes at most the given number of available elements from
      * this queue and adds them to the given collection.  A failure
      * encountered while attempting to add elements to
-     * collection <tt>c</tt> may result in elements being in neither,
+     * collection {@code c} may result in elements being in neither,
      * either or both collections when the associated exception is
      * thrown.  Attempts to drain a queue to itself result in
-     * <tt>IllegalArgumentException</tt>. Further, the behavior of
+     * {@code IllegalArgumentException}. Further, the behavior of
      * this operation is undefined if the specified collection is
      * modified while the operation is in progress.
      *
diff --git a/luni/src/main/java/java/util/concurrent/BrokenBarrierException.java b/luni/src/main/java/java/util/concurrent/BrokenBarrierException.java
index 76fae13..9fe707d 100644
--- a/luni/src/main/java/java/util/concurrent/BrokenBarrierException.java
+++ b/luni/src/main/java/java/util/concurrent/BrokenBarrierException.java
@@ -15,19 +15,18 @@
  *
  * @since 1.5
  * @author Doug Lea
- *
  */
 public class BrokenBarrierException extends Exception {
     private static final long serialVersionUID = 7117394618823254244L;
 
     /**
-     * Constructs a <tt>BrokenBarrierException</tt> with no specified detail
+     * Constructs a {@code BrokenBarrierException} with no specified detail
      * message.
      */
     public BrokenBarrierException() {}
 
     /**
-     * Constructs a <tt>BrokenBarrierException</tt> with the specified
+     * Constructs a {@code BrokenBarrierException} with the specified
      * detail message.
      *
      * @param message the detail message
diff --git a/luni/src/main/java/java/util/concurrent/Callable.java b/luni/src/main/java/java/util/concurrent/Callable.java
index 293544b..a3b3883 100644
--- a/luni/src/main/java/java/util/concurrent/Callable.java
+++ b/luni/src/main/java/java/util/concurrent/Callable.java
@@ -9,21 +9,21 @@
 /**
  * A task that returns a result and may throw an exception.
  * Implementors define a single method with no arguments called
- * <tt>call</tt>.
+ * {@code call}.
  *
- * <p>The <tt>Callable</tt> interface is similar to {@link
+ * <p>The {@code Callable} interface is similar to {@link
  * java.lang.Runnable}, in that both are designed for classes whose
  * instances are potentially executed by another thread.  A
- * <tt>Runnable</tt>, however, does not return a result and cannot
+ * {@code Runnable}, however, does not return a result and cannot
  * throw a checked exception.
  *
- * <p> The {@link Executors} class contains utility methods to
- * convert from other common forms to <tt>Callable</tt> classes.
+ * <p>The {@link Executors} class contains utility methods to
+ * convert from other common forms to {@code Callable} classes.
  *
  * @see Executor
  * @since 1.5
  * @author Doug Lea
- * @param <V> the result type of method <tt>call</tt>
+ * @param <V> the result type of method {@code call}
  */
 public interface Callable<V> {
     /**
diff --git a/luni/src/main/java/java/util/concurrent/CancellationException.java b/luni/src/main/java/java/util/concurrent/CancellationException.java
index dc452e4..25ab271 100644
--- a/luni/src/main/java/java/util/concurrent/CancellationException.java
+++ b/luni/src/main/java/java/util/concurrent/CancellationException.java
@@ -18,12 +18,12 @@
     private static final long serialVersionUID = -9202173006928992231L;
 
     /**
-     * Constructs a <tt>CancellationException</tt> with no detail message.
+     * Constructs a {@code CancellationException} with no detail message.
      */
     public CancellationException() {}
 
     /**
-     * Constructs a <tt>CancellationException</tt> with the specified detail
+     * Constructs a {@code CancellationException} with the specified detail
      * message.
      *
      * @param message the detail message
diff --git a/luni/src/main/java/java/util/concurrent/CompletionService.java b/luni/src/main/java/java/util/concurrent/CompletionService.java
index 7b0931c..0607596 100644
--- a/luni/src/main/java/java/util/concurrent/CompletionService.java
+++ b/luni/src/main/java/java/util/concurrent/CompletionService.java
@@ -9,17 +9,17 @@
 /**
  * A service that decouples the production of new asynchronous tasks
  * from the consumption of the results of completed tasks.  Producers
- * <tt>submit</tt> tasks for execution. Consumers <tt>take</tt>
+ * {@code submit} tasks for execution. Consumers {@code take}
  * completed tasks and process their results in the order they
- * complete.  A <tt>CompletionService</tt> can for example be used to
- * manage asynchronous IO, in which tasks that perform reads are
+ * complete.  A {@code CompletionService} can for example be used to
+ * manage asynchronous I/O, in which tasks that perform reads are
  * submitted in one part of a program or system, and then acted upon
  * in a different part of the program when the reads complete,
  * possibly in a different order than they were requested.
  *
- * <p>Typically, a <tt>CompletionService</tt> relies on a separate
+ * <p>Typically, a {@code CompletionService} relies on a separate
  * {@link Executor} to actually execute the tasks, in which case the
- * <tt>CompletionService</tt> only manages an internal completion
+ * {@code CompletionService} only manages an internal completion
  * queue. The {@link ExecutorCompletionService} class provides an
  * implementation of this approach.
  *
@@ -28,7 +28,6 @@
  * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
  * actions taken by that task, which in turn <i>happen-before</i>
  * actions following a successful return from the corresponding {@code take()}.
- *
  */
 public interface CompletionService<V> {
     /**
@@ -52,7 +51,7 @@
      * @param task the task to submit
      * @param result the result to return upon successful completion
      * @return a Future representing pending completion of the task,
-     *         and whose <tt>get()</tt> method will return the given
+     *         and whose {@code get()} method will return the given
      *         result value upon completion
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
@@ -69,13 +68,12 @@
      */
     Future<V> take() throws InterruptedException;
 
-
     /**
      * Retrieves and removes the Future representing the next
-     * completed task or <tt>null</tt> if none are present.
+     * completed task, or {@code null} if none are present.
      *
      * @return the Future representing the next completed task, or
-     *         <tt>null</tt> if none are present
+     *         {@code null} if none are present
      */
     Future<V> poll();
 
@@ -85,11 +83,11 @@
      * time if none are yet present.
      *
      * @param timeout how long to wait before giving up, in units of
-     *        <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     *        <tt>timeout</tt> parameter
+     *        {@code unit}
+     * @param unit a {@code TimeUnit} determining how to interpret the
+     *        {@code timeout} parameter
      * @return the Future representing the next completed task or
-     *         <tt>null</tt> if the specified waiting time elapses
+     *         {@code null} if the specified waiting time elapses
      *         before one is present
      * @throws InterruptedException if interrupted while waiting
      */
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
index 30adb36..54b53ae 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
@@ -63,7 +63,6 @@
  * @author Martin Buchholz
  * @param <E> the type of elements held in this collection
  */
-
 public class ConcurrentLinkedDeque<E>
     extends AbstractCollection<E>
     implements Deque<E>, java.io.Serializable {
@@ -790,7 +789,7 @@
      * Creates an array list and fills it with elements of this list.
      * Used by toArray.
      *
-     * @return the arrayList
+     * @return the array list
      */
     private ArrayList<E> toArrayList() {
         ArrayList<E> list = new ArrayList<E>();
@@ -1360,11 +1359,10 @@
     }
 
     /**
-     * Saves the state to a stream (that is, serializes it).
+     * Saves this deque to a stream (that is, serializes it).
      *
      * @serialData All of the elements (each an {@code E}) in
      * the proper order, followed by a null
-     * @param s the stream
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
@@ -1384,8 +1382,7 @@
     }
 
     /**
-     * Reconstitutes the instance from a stream (that is, deserializes it).
-     * @param s the stream
+     * Reconstitutes this deque from a stream (that is, deserializes it).
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
@@ -1408,7 +1405,6 @@
         initHeadTail(h, t);
     }
 
-
     private boolean casHead(Node<E> cmp, Node<E> val) {
         return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
     }
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
index a0a26fd..873f825 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
@@ -69,7 +69,6 @@
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this collection
- *
  */
 public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
         implements Queue<E>, java.io.Serializable {
@@ -218,7 +217,6 @@
      */
     private transient volatile Node<E> tail;
 
-
     /**
      * Creates a {@code ConcurrentLinkedQueue} that is initially empty.
      */
@@ -268,7 +266,7 @@
     }
 
     /**
-     * Try to CAS head to p. If successful, repoint old head to itself
+     * Tries to CAS head to p. If successful, repoint old head to itself
      * as sentinel for succ(), below.
      */
     final void updateHead(Node<E> h, Node<E> p) {
@@ -717,11 +715,10 @@
     }
 
     /**
-     * Saves the state to a stream (that is, serializes it).
+     * Saves this queue to a stream (that is, serializes it).
      *
      * @serialData All of the elements (each an {@code E}) in
      * the proper order, followed by a null
-     * @param s the stream
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
@@ -741,8 +738,7 @@
     }
 
     /**
-     * Reconstitutes the instance from a stream (that is, deserializes it).
-     * @param s the stream
+     * Reconstitutes this queue from a stream (that is, deserializes it).
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
index 3405acf..27feeb2 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
@@ -13,7 +13,7 @@
 
 /**
  * A {@link java.util.Map} providing additional atomic
- * <tt>putIfAbsent</tt>, <tt>remove</tt>, and <tt>replace</tt> methods.
+ * {@code putIfAbsent}, {@code remove}, and {@code replace} methods.
  *
  * <p>Memory consistency effects: As with other concurrent
  * collections, actions in a thread prior to placing an object into a
@@ -27,7 +27,7 @@
  * @param <K> the type of keys maintained by this map
  * @param <V> the type of mapped values
  */
-public interface ConcurrentMap<K, V> extends Map<K, V> {
+public interface ConcurrentMap<K,V> extends Map<K,V> {
     /**
      * If the specified key is not already associated
      * with a value, associate it with the given value.
@@ -43,11 +43,11 @@
      * @param key key with which the specified value is to be associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with the specified key, or
-     *         <tt>null</tt> if there was no mapping for the key.
-     *         (A <tt>null</tt> return can also indicate that the map
-     *         previously associated <tt>null</tt> with the key,
+     *         {@code null} if there was no mapping for the key.
+     *         (A {@code null} return can also indicate that the map
+     *         previously associated {@code null} with the key,
      *         if the implementation supports null values.)
-     * @throws UnsupportedOperationException if the <tt>put</tt> operation
+     * @throws UnsupportedOperationException if the {@code put} operation
      *         is not supported by this map
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
@@ -55,7 +55,6 @@
      *         and this map does not permit null keys or values
      * @throws IllegalArgumentException if some property of the specified key
      *         or value prevents it from being stored in this map
-     *
      */
     V putIfAbsent(K key, V value);
 
@@ -73,8 +72,8 @@
      *
      * @param key key with which the specified value is associated
      * @param value value expected to be associated with the specified key
-     * @return <tt>true</tt> if the value was removed
-     * @throws UnsupportedOperationException if the <tt>remove</tt> operation
+     * @return {@code true} if the value was removed
+     * @throws UnsupportedOperationException if the {@code remove} operation
      *         is not supported by this map
      * @throws ClassCastException if the key or value is of an inappropriate
      *         type for this map
@@ -100,8 +99,8 @@
      * @param key key with which the specified value is associated
      * @param oldValue value expected to be associated with the specified key
      * @param newValue value to be associated with the specified key
-     * @return <tt>true</tt> if the value was replaced
-     * @throws UnsupportedOperationException if the <tt>put</tt> operation
+     * @return {@code true} if the value was replaced
+     * @throws UnsupportedOperationException if the {@code put} operation
      *         is not supported by this map
      * @throws ClassCastException if the class of a specified key or value
      *         prevents it from being stored in this map
@@ -126,11 +125,11 @@
      * @param key key with which the specified value is associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with the specified key, or
-     *         <tt>null</tt> if there was no mapping for the key.
-     *         (A <tt>null</tt> return can also indicate that the map
-     *         previously associated <tt>null</tt> with the key,
+     *         {@code null} if there was no mapping for the key.
+     *         (A {@code null} return can also indicate that the map
+     *         previously associated {@code null} with the key,
      *         if the implementation supports null values.)
-     * @throws UnsupportedOperationException if the <tt>put</tt> operation
+     * @throws UnsupportedOperationException if the {@code put} operation
      *         is not supported by this map
      * @throws ClassCastException if the class of the specified key or value
      *         prevents it from being stored in this map
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
index ea99886..e87fbee 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
@@ -38,7 +38,6 @@
      */
     ConcurrentNavigableMap<K,V> headMap(K toKey, boolean inclusive);
 
-
     /**
      * @throws ClassCastException       {@inheritDoc}
      * @throws NullPointerException     {@inheritDoc}
@@ -73,7 +72,7 @@
      * reflected in the descending map, and vice-versa.
      *
      * <p>The returned map has an ordering equivalent to
-     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+     * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
      * The expression {@code m.descendingMap().descendingMap()} returns a
      * view of {@code m} essentially equivalent to {@code m}.
      *
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
index d0d6f14..803cd49 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
@@ -20,8 +20,8 @@
  * <p>This class implements a concurrent variant of <a
  * href="http://en.wikipedia.org/wiki/Skip_list" target="_top">SkipLists</a>
  * providing expected average <i>log(n)</i> time cost for the
- * <tt>containsKey</tt>, <tt>get</tt>, <tt>put</tt> and
- * <tt>remove</tt> operations and their variants.  Insertion, removal,
+ * {@code containsKey}, {@code get}, {@code put} and
+ * {@code remove} operations and their variants.  Insertion, removal,
  * update, and access operations safely execute concurrently by
  * multiple threads.  Iterators are <i>weakly consistent</i>, returning
  * elements reflecting the state of the map at some point at or since
@@ -30,28 +30,28 @@
  * other operations. Ascending key ordered views and their iterators
  * are faster than descending ones.
  *
- * <p>All <tt>Map.Entry</tt> pairs returned by methods in this class
+ * <p>All {@code Map.Entry} pairs returned by methods in this class
  * and its views represent snapshots of mappings at the time they were
- * produced. They do <em>not</em> support the <tt>Entry.setValue</tt>
+ * produced. They do <em>not</em> support the {@code Entry.setValue}
  * method. (Note however that it is possible to change mappings in the
- * associated map using <tt>put</tt>, <tt>putIfAbsent</tt>, or
- * <tt>replace</tt>, depending on exactly which effect you need.)
+ * associated map using {@code put}, {@code putIfAbsent}, or
+ * {@code replace}, depending on exactly which effect you need.)
  *
- * <p>Beware that, unlike in most collections, the <tt>size</tt>
+ * <p>Beware that, unlike in most collections, the {@code size}
  * method is <em>not</em> a constant-time operation. Because of the
  * asynchronous nature of these maps, determining the current number
  * of elements requires a traversal of the elements, and so may report
  * inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations <tt>putAll</tt>, <tt>equals</tt>,
- * <tt>toArray</tt>, <tt>containsValue</tt>, and <tt>clear</tt> are
+ * Additionally, the bulk operations {@code putAll}, {@code equals},
+ * {@code toArray}, {@code containsValue}, and {@code clear} are
  * <em>not</em> guaranteed to be performed atomically. For example, an
- * iterator operating concurrently with a <tt>putAll</tt> operation
+ * iterator operating concurrently with a {@code putAll} operation
  * might view only some of the added elements.
  *
  * <p>This class and its views and iterators implement all of the
  * <em>optional</em> methods of the {@link Map} and {@link Iterator}
  * interfaces. Like most other concurrent collections, this class does
- * <em>not</em> permit the use of <tt>null</tt> keys or values because some
+ * <em>not</em> permit the use of {@code null} keys or values because some
  * null return values cannot be reliably distinguished from the absence of
  * elements.
  *
@@ -60,6 +60,7 @@
  * @param <V> the type of mapped values
  * @since 1.6
  */
+@SuppressWarnings("unchecked")
 public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
     implements ConcurrentNavigableMap<K,V>,
                Cloneable,
@@ -408,7 +409,7 @@
          * because callers will have already read value field and need
          * to use that read (not another done here) and so directly
          * test if value points to node.
-         * @param n a possibly null reference to a node
+         *
          * @return true if this node is a marker node
          */
         boolean isMarker() {
@@ -457,7 +458,7 @@
          * Returns value if this node contains a valid key-value pair,
          * else null.
          * @return this node's value if it isn't a marker or header or
-         * is deleted, else null.
+         * is deleted, else null
          */
         V getValidValue() {
             Object v = value;
@@ -810,7 +811,7 @@
      * Main insertion method.  Adds element if not present, or
      * replaces value if present and onlyIfAbsent is false.
      * @param kkey the key
-     * @param value  the value that must be associated with key
+     * @param value the value that must be associated with key
      * @param onlyIfAbsent if should not insert if already present
      * @return the old value, or null if newly inserted
      */
@@ -934,7 +935,7 @@
      * Adds given index nodes from given level down to 1.
      * @param idx the topmost index node being inserted
      * @param h the value of head to use to insert. This must be
-     * snapshotted by callers to provide correct insertion level
+     * snapshotted by callers to provide correct insertion level.
      * @param indexLevel the level of the index
      */
     private void addIndex(Index<K,V> idx, HeadIndex<K,V> h, int indexLevel) {
@@ -1359,7 +1360,7 @@
      * comparator.
      *
      * @param comparator the comparator that will be used to order this map.
-     *        If <tt>null</tt>, the {@linkplain Comparable natural
+     *        If {@code null}, the {@linkplain Comparable natural
      *        ordering} of the keys will be used.
      */
     public ConcurrentSkipListMap(Comparator<? super K> comparator) {
@@ -1373,7 +1374,7 @@
      * the keys.
      *
      * @param  m the map whose mappings are to be placed in this map
-     * @throws ClassCastException if the keys in <tt>m</tt> are not
+     * @throws ClassCastException if the keys in {@code m} are not
      *         {@link Comparable}, or are not mutually comparable
      * @throws NullPointerException if the specified map or any of its keys
      *         or values are null
@@ -1400,7 +1401,7 @@
     }
 
     /**
-     * Returns a shallow copy of this <tt>ConcurrentSkipListMap</tt>
+     * Returns a shallow copy of this {@code ConcurrentSkipListMap}
      * instance. (The keys and values themselves are not cloned.)
      *
      * @return a shallow copy of this map
@@ -1477,11 +1478,11 @@
     /* ---------------- Serialization -------------- */
 
     /**
-     * Saves the state of this map to a stream (that is, serializes it).
+     * Saves this map to a stream (that is, serializes it).
      *
      * @serialData The key (Object) and value (Object) for each
      * key-value mapping represented by the map, followed by
-     * <tt>null</tt>. The key-value mappings are emitted in key-order
+     * {@code null}. The key-value mappings are emitted in key-order
      * (as determined by the Comparator, or by the keys' natural
      * ordering if no Comparator).
      */
@@ -1502,9 +1503,7 @@
     }
 
     /**
-     * Reconstitutes the map from a stream (that is, deserializes it).
-     *
-     * @param s the stream
+     * Reconstitutes this map from a stream (that is, deserializes it).
      */
     private void readObject(final java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
@@ -1567,11 +1566,11 @@
     /* ------ Map API methods ------ */
 
     /**
-     * Returns <tt>true</tt> if this map contains a mapping for the specified
+     * Returns {@code true} if this map contains a mapping for the specified
      * key.
      *
      * @param key key whose presence in this map is to be tested
-     * @return <tt>true</tt> if this map contains a mapping for the specified key
+     * @return {@code true} if this map contains a mapping for the specified key
      * @throws ClassCastException if the specified key cannot be compared
      *         with the keys currently in the map
      * @throws NullPointerException if the specified key is null
@@ -1606,7 +1605,7 @@
      * @param key key with which the specified value is to be associated
      * @param value value to be associated with the specified key
      * @return the previous value associated with the specified key, or
-     *         <tt>null</tt> if there was no mapping for the key
+     *         {@code null} if there was no mapping for the key
      * @throws ClassCastException if the specified key cannot be compared
      *         with the keys currently in the map
      * @throws NullPointerException if the specified key or value is null
@@ -1622,7 +1621,7 @@
      *
      * @param  key key for which mapping should be removed
      * @return the previous value associated with the specified key, or
-     *         <tt>null</tt> if there was no mapping for the key
+     *         {@code null} if there was no mapping for the key
      * @throws ClassCastException if the specified key cannot be compared
      *         with the keys currently in the map
      * @throws NullPointerException if the specified key is null
@@ -1632,15 +1631,15 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map maps one or more keys to the
+     * Returns {@code true} if this map maps one or more keys to the
      * specified value.  This operation requires time linear in the
      * map size. Additionally, it is possible for the map to change
      * during execution of this method, in which case the returned
      * result may be inaccurate.
      *
      * @param value value whose presence in this map is to be tested
-     * @return <tt>true</tt> if a mapping to <tt>value</tt> exists;
-     *         <tt>false</tt> otherwise
+     * @return {@code true} if a mapping to {@code value} exists;
+     *         {@code false} otherwise
      * @throws NullPointerException if the specified value is null
      */
     public boolean containsValue(Object value) {
@@ -1656,8 +1655,8 @@
 
     /**
      * Returns the number of key-value mappings in this map.  If this map
-     * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
-     * returns <tt>Integer.MAX_VALUE</tt>.
+     * contains more than {@code Integer.MAX_VALUE} elements, it
+     * returns {@code Integer.MAX_VALUE}.
      *
      * <p>Beware that, unlike in most collections, this method is
      * <em>NOT</em> a constant-time operation. Because of the
@@ -1680,8 +1679,8 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this map contains no key-value mappings.
-     * @return <tt>true</tt> if this map contains no key-value mappings
+     * Returns {@code true} if this map contains no key-value mappings.
+     * @return {@code true} if this map contains no key-value mappings
      */
     public boolean isEmpty() {
         return findFirst() == null;
@@ -1743,12 +1742,12 @@
      * The collection is backed by the map, so changes to the map are
      * reflected in the collection, and vice-versa.  The collection
      * supports element removal, which removes the corresponding
-     * mapping from the map, via the <tt>Iterator.remove</tt>,
-     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
-     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
-     * support the <tt>add</tt> or <tt>addAll</tt> operations.
+     * mapping from the map, via the {@code Iterator.remove},
+     * {@code Collection.remove}, {@code removeAll},
+     * {@code retainAll} and {@code clear} operations.  It does not
+     * support the {@code add} or {@code addAll} operations.
      *
-     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
      * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
@@ -1765,20 +1764,20 @@
      * The set is backed by the map, so changes to the map are
      * reflected in the set, and vice-versa.  The set supports element
      * removal, which removes the corresponding mapping from the map,
-     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
-     * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt>
-     * operations.  It does not support the <tt>add</tt> or
-     * <tt>addAll</tt> operations.
+     * via the {@code Iterator.remove}, {@code Set.remove},
+     * {@code removeAll}, {@code retainAll} and {@code clear}
+     * operations.  It does not support the {@code add} or
+     * {@code addAll} operations.
      *
-     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * <p>The view's {@code iterator} is a "weakly consistent" iterator
      * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
      *
-     * <p>The <tt>Map.Entry</tt> elements returned by
-     * <tt>iterator.next()</tt> do <em>not</em> support the
-     * <tt>setValue</tt> operation.
+     * <p>The {@code Map.Entry} elements returned by
+     * {@code iterator.next()} do <em>not</em> support the
+     * {@code setValue} operation.
      *
      * @return a set view of the mappings contained in this map,
      *         sorted in ascending key order
@@ -1802,15 +1801,15 @@
 
     /**
      * Compares the specified object with this map for equality.
-     * Returns <tt>true</tt> if the given object is also a map and the
+     * Returns {@code true} if the given object is also a map and the
      * two maps represent the same mappings.  More formally, two maps
-     * <tt>m1</tt> and <tt>m2</tt> represent the same mappings if
-     * <tt>m1.entrySet().equals(m2.entrySet())</tt>.  This
+     * {@code m1} and {@code m2} represent the same mappings if
+     * {@code m1.entrySet().equals(m2.entrySet())}.  This
      * operation may return misleading results if either map is
      * concurrently modified during execution of this method.
      *
      * @param o object to be compared for equality with this map
-     * @return <tt>true</tt> if the specified object is equal to this map
+     * @return {@code true} if the specified object is equal to this map
      */
     public boolean equals(Object o) {
         if (o == this)
@@ -1842,7 +1841,7 @@
      * {@inheritDoc}
      *
      * @return the previous value associated with the specified key,
-     *         or <tt>null</tt> if there was no mapping for the key
+     *         or {@code null} if there was no mapping for the key
      * @throws ClassCastException if the specified key cannot be compared
      *         with the keys currently in the map
      * @throws NullPointerException if the specified key or value is null
@@ -1897,7 +1896,7 @@
      * {@inheritDoc}
      *
      * @return the previous value associated with the specified key,
-     *         or <tt>null</tt> if there was no mapping for the key
+     *         or {@code null} if there was no mapping for the key
      * @throws ClassCastException if the specified key cannot be compared
      *         with the keys currently in the map
      * @throws NullPointerException if the specified key or value is null
@@ -2014,9 +2013,9 @@
 
     /**
      * Returns a key-value mapping associated with the greatest key
-     * strictly less than the given key, or <tt>null</tt> if there is
+     * strictly less than the given key, or {@code null} if there is
      * no such key. The returned entry does <em>not</em> support the
-     * <tt>Entry.setValue</tt> method.
+     * {@code Entry.setValue} method.
      *
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException if the specified key is null
@@ -2036,9 +2035,9 @@
 
     /**
      * Returns a key-value mapping associated with the greatest key
-     * less than or equal to the given key, or <tt>null</tt> if there
+     * less than or equal to the given key, or {@code null} if there
      * is no such key. The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      *
      * @param key the key
      * @throws ClassCastException {@inheritDoc}
@@ -2060,9 +2059,9 @@
 
     /**
      * Returns a key-value mapping associated with the least key
-     * greater than or equal to the given key, or <tt>null</tt> if
+     * greater than or equal to the given key, or {@code null} if
      * there is no such entry. The returned entry does <em>not</em>
-     * support the <tt>Entry.setValue</tt> method.
+     * support the {@code Entry.setValue} method.
      *
      * @throws ClassCastException {@inheritDoc}
      * @throws NullPointerException if the specified key is null
@@ -2082,9 +2081,9 @@
 
     /**
      * Returns a key-value mapping associated with the least key
-     * strictly greater than the given key, or <tt>null</tt> if there
+     * strictly greater than the given key, or {@code null} if there
      * is no such key. The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      *
      * @param key the key
      * @throws ClassCastException {@inheritDoc}
@@ -2106,9 +2105,9 @@
 
     /**
      * Returns a key-value mapping associated with the least
-     * key in this map, or <tt>null</tt> if the map is empty.
+     * key in this map, or {@code null} if the map is empty.
      * The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      */
     public Map.Entry<K,V> firstEntry() {
         for (;;) {
@@ -2123,9 +2122,9 @@
 
     /**
      * Returns a key-value mapping associated with the greatest
-     * key in this map, or <tt>null</tt> if the map is empty.
+     * key in this map, or {@code null} if the map is empty.
      * The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      */
     public Map.Entry<K,V> lastEntry() {
         for (;;) {
@@ -2140,9 +2139,9 @@
 
     /**
      * Removes and returns a key-value mapping associated with
-     * the least key in this map, or <tt>null</tt> if the map is empty.
+     * the least key in this map, or {@code null} if the map is empty.
      * The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      */
     public Map.Entry<K,V> pollFirstEntry() {
         return doRemoveFirstEntry();
@@ -2150,9 +2149,9 @@
 
     /**
      * Removes and returns a key-value mapping associated with
-     * the greatest key in this map, or <tt>null</tt> if the map is empty.
+     * the greatest key in this map, or {@code null} if the map is empty.
      * The returned entry does <em>not</em> support
-     * the <tt>Entry.setValue</tt> method.
+     * the {@code Entry.setValue} method.
      */
     public Map.Entry<K,V> pollLastEntry() {
         return doRemoveLastEntry();
@@ -2268,7 +2267,7 @@
 
     static final <E> List<E> toList(Collection<E> c) {
         // Using size() here would be a pessimization.
-        List<E> list = new ArrayList<E>();
+        ArrayList<E> list = new ArrayList<E>();
         for (E e : c)
             list.add(e);
         return list;
@@ -2312,7 +2311,7 @@
             Collection<?> c = (Collection<?>) o;
             try {
                 return containsAll(c) && c.containsAll(this);
-            } catch (ClassCastException unused)   {
+            } catch (ClassCastException unused) {
                 return false;
             } catch (NullPointerException unused) {
                 return false;
@@ -2421,7 +2420,7 @@
             Collection<?> c = (Collection<?>) o;
             try {
                 return containsAll(c) && c.containsAll(this);
-            } catch (ClassCastException unused)   {
+            } catch (ClassCastException unused) {
                 return false;
             } catch (NullPointerException unused) {
                 return false;
@@ -2438,8 +2437,8 @@
      * underlying maps, differing in that mappings outside their range are
      * ignored, and attempts to add mappings outside their ranges result
      * in {@link IllegalArgumentException}.  Instances of this class are
-     * constructed only using the <tt>subMap</tt>, <tt>headMap</tt>, and
-     * <tt>tailMap</tt> methods of their underlying maps.
+     * constructed only using the {@code subMap}, {@code headMap}, and
+     * {@code tailMap} methods of their underlying maps.
      *
      * @serial include
      */
@@ -2467,7 +2466,7 @@
         private transient Collection<V> valuesView;
 
         /**
-         * Creates a new submap, initializing all fields
+         * Creates a new submap, initializing all fields.
          */
         SubMap(ConcurrentSkipListMap<K,V> map,
                K fromKey, boolean fromInclusive,
@@ -2516,7 +2515,7 @@
         }
 
         /**
-         * Returns true if node key is less than upper bound of range
+         * Returns true if node key is less than upper bound of range.
          */
         private boolean isBeforeEnd(ConcurrentSkipListMap.Node<K,V> n) {
             if (n == null)
@@ -2534,7 +2533,7 @@
 
         /**
          * Returns lowest node. This node might not be in range, so
-         * most usages need to check bounds
+         * most usages need to check bounds.
          */
         private ConcurrentSkipListMap.Node<K,V> loNode() {
             if (lo == null)
@@ -2547,7 +2546,7 @@
 
         /**
          * Returns highest node. This node might not be in range, so
-         * most usages need to check bounds
+         * most usages need to check bounds.
          */
         private ConcurrentSkipListMap.Node<K,V> hiNode() {
             if (hi == null)
@@ -2559,7 +2558,7 @@
         }
 
         /**
-         * Returns lowest absolute key (ignoring directonality)
+         * Returns lowest absolute key (ignoring directonality).
          */
         private K lowestKey() {
             ConcurrentSkipListMap.Node<K,V> n = loNode();
@@ -2570,7 +2569,7 @@
         }
 
         /**
-         * Returns highest absolute key (ignoring directonality)
+         * Returns highest absolute key (ignoring directonality).
          */
         private K highestKey() {
             ConcurrentSkipListMap.Node<K,V> n = hiNode();
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
index 71431a9..f1402b6 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
@@ -19,7 +19,7 @@
  * on which constructor is used.
  *
  * <p>This implementation provides expected average <i>log(n)</i> time
- * cost for the <tt>contains</tt>, <tt>add</tt>, and <tt>remove</tt>
+ * cost for the {@code contains}, {@code add}, and {@code remove}
  * operations and their variants.  Insertion, removal, and access
  * operations safely execute concurrently by multiple threads.
  * Iterators are <i>weakly consistent</i>, returning elements
@@ -29,23 +29,23 @@
  * other operations.  Ascending ordered views and their iterators are
  * faster than descending ones.
  *
- * <p>Beware that, unlike in most collections, the <tt>size</tt>
+ * <p>Beware that, unlike in most collections, the {@code size}
  * method is <em>not</em> a constant-time operation. Because of the
  * asynchronous nature of these sets, determining the current number
  * of elements requires a traversal of the elements, and so may report
  * inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations <tt>addAll</tt>,
- * <tt>removeAll</tt>, <tt>retainAll</tt>, <tt>containsAll</tt>,
- * <tt>equals</tt>, and <tt>toArray</tt> are <em>not</em> guaranteed
+ * Additionally, the bulk operations {@code addAll},
+ * {@code removeAll}, {@code retainAll}, {@code containsAll},
+ * {@code equals}, and {@code toArray} are <em>not</em> guaranteed
  * to be performed atomically. For example, an iterator operating
- * concurrently with an <tt>addAll</tt> operation might view only some
+ * concurrently with an {@code addAll} operation might view only some
  * of the added elements.
  *
  * <p>This class and its iterators implement all of the
  * <em>optional</em> methods of the {@link Set} and {@link Iterator}
  * interfaces. Like most other concurrent collection implementations,
- * this class does not permit the use of <tt>null</tt> elements,
- * because <tt>null</tt> arguments and return values cannot be reliably
+ * this class does not permit the use of {@code null} elements,
+ * because {@code null} arguments and return values cannot be reliably
  * distinguished from the absence of elements.
  *
  * @author Doug Lea
@@ -61,7 +61,7 @@
     /**
      * The underlying map. Uses Boolean.TRUE as value for each
      * element.  This field is declared final for the sake of thread
-     * safety, which entails some ugliness in clone()
+     * safety, which entails some ugliness in clone().
      */
     private final ConcurrentNavigableMap<E,Object> m;
 
@@ -78,7 +78,7 @@
      * the specified comparator.
      *
      * @param comparator the comparator that will be used to order this set.
-     *        If <tt>null</tt>, the {@linkplain Comparable natural
+     *        If {@code null}, the {@linkplain Comparable natural
      *        ordering} of the elements will be used.
      */
     public ConcurrentSkipListSet(Comparator<? super E> comparator) {
@@ -91,7 +91,7 @@
      * {@linkplain Comparable natural ordering}.
      *
      * @param c The elements that will comprise the new set
-     * @throws ClassCastException if the elements in <tt>c</tt> are
+     * @throws ClassCastException if the elements in {@code c} are
      *         not {@link Comparable}, or are not mutually comparable
      * @throws NullPointerException if the specified collection or any
      *         of its elements are null
@@ -122,7 +122,7 @@
     }
 
     /**
-     * Returns a shallow copy of this <tt>ConcurrentSkipListSet</tt>
+     * Returns a shallow copy of this {@code ConcurrentSkipListSet}
      * instance. (The elements themselves are not cloned.)
      *
      * @return a shallow copy of this set
@@ -143,8 +143,8 @@
 
     /**
      * Returns the number of elements in this set.  If this set
-     * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
-     * returns <tt>Integer.MAX_VALUE</tt>.
+     * contains more than {@code Integer.MAX_VALUE} elements, it
+     * returns {@code Integer.MAX_VALUE}.
      *
      * <p>Beware that, unlike in most collections, this method is
      * <em>NOT</em> a constant-time operation. Because of the
@@ -162,20 +162,20 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains no elements.
-     * @return <tt>true</tt> if this set contains no elements
+     * Returns {@code true} if this set contains no elements.
+     * @return {@code true} if this set contains no elements
      */
     public boolean isEmpty() {
         return m.isEmpty();
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this set
-     * contains an element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+     * Returns {@code true} if this set contains the specified element.
+     * More formally, returns {@code true} if and only if this set
+     * contains an element {@code e} such that {@code o.equals(e)}.
      *
      * @param o object to be checked for containment in this set
-     * @return <tt>true</tt> if this set contains the specified element
+     * @return {@code true} if this set contains the specified element
      * @throws ClassCastException if the specified element cannot be
      *         compared with the elements currently in this set
      * @throws NullPointerException if the specified element is null
@@ -186,15 +186,15 @@
 
     /**
      * Adds the specified element to this set if it is not already present.
-     * More formally, adds the specified element <tt>e</tt> to this set if
-     * the set contains no element <tt>e2</tt> such that <tt>e.equals(e2)</tt>.
+     * More formally, adds the specified element {@code e} to this set if
+     * the set contains no element {@code e2} such that {@code e.equals(e2)}.
      * If this set already contains the element, the call leaves the set
-     * unchanged and returns <tt>false</tt>.
+     * unchanged and returns {@code false}.
      *
      * @param e element to be added to this set
-     * @return <tt>true</tt> if this set did not already contain the
+     * @return {@code true} if this set did not already contain the
      *         specified element
-     * @throws ClassCastException if <tt>e</tt> cannot be compared
+     * @throws ClassCastException if {@code e} cannot be compared
      *         with the elements currently in this set
      * @throws NullPointerException if the specified element is null
      */
@@ -204,15 +204,15 @@
 
     /**
      * Removes the specified element from this set if it is present.
-     * More formally, removes an element <tt>e</tt> such that
-     * <tt>o.equals(e)</tt>, if this set contains such an element.
-     * Returns <tt>true</tt> if this set contained the element (or
+     * More formally, removes an element {@code e} such that
+     * {@code o.equals(e)}, if this set contains such an element.
+     * Returns {@code true} if this set contained the element (or
      * equivalently, if this set changed as a result of the call).
      * (This set will not contain the element once the call returns.)
      *
      * @param o object to be removed from this set, if present
-     * @return <tt>true</tt> if this set contained the specified element
-     * @throws ClassCastException if <tt>o</tt> cannot be compared
+     * @return {@code true} if this set contained the specified element
+     * @throws ClassCastException if {@code o} cannot be compared
      *         with the elements currently in this set
      * @throws NullPointerException if the specified element is null
      */
@@ -250,7 +250,7 @@
 
     /**
      * Compares the specified object with this set for equality.  Returns
-     * <tt>true</tt> if the specified object is also a set, the two sets
+     * {@code true} if the specified object is also a set, the two sets
      * have the same size, and every member of the specified set is
      * contained in this set (or equivalently, every member of this set is
      * contained in the specified set).  This definition ensures that the
@@ -258,7 +258,7 @@
      * set interface.
      *
      * @param o the object to be compared for equality with this set
-     * @return <tt>true</tt> if the specified object is equal to this set
+     * @return {@code true} if the specified object is equal to this set
      */
     public boolean equals(Object o) {
         // Override AbstractSet version to avoid calling size()
@@ -269,7 +269,7 @@
         Collection<?> c = (Collection<?>) o;
         try {
             return containsAll(c) && c.containsAll(this);
-        } catch (ClassCastException unused)   {
+        } catch (ClassCastException unused) {
             return false;
         } catch (NullPointerException unused) {
             return false;
@@ -283,7 +283,7 @@
      * value is the <i>asymmetric set difference</i> of the two sets.
      *
      * @param  c collection containing elements to be removed from this set
-     * @return <tt>true</tt> if this set changed as a result of the call
+     * @return {@code true} if this set changed as a result of the call
      * @throws ClassCastException if the types of one or more elements in this
      *         set are incompatible with the specified collection
      * @throws NullPointerException if the specified collection or any
@@ -431,7 +431,7 @@
      * reflected in the descending set, and vice-versa.
      *
      * <p>The returned set has an ordering equivalent to
-     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+     * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
      * The expression {@code s.descendingSet().descendingSet()} returns a
      * view of {@code s} essentially equivalent to {@code s}.
      *
diff --git a/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java b/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
index 1f37bc9..6fa8feb 100644
--- a/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
+++ b/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
@@ -20,17 +20,17 @@
  *       vastly outnumber mutative operations, and you need
  *       to prevent interference among threads during traversal.
  *  <li>It is thread-safe.
- *  <li>Mutative operations (<tt>add</tt>, <tt>set</tt>, <tt>remove</tt>, etc.)
+ *  <li>Mutative operations ({@code add}, {@code set}, {@code remove}, etc.)
  *      are expensive since they usually entail copying the entire underlying
  *      array.
- *  <li>Iterators do not support the mutative <tt>remove</tt> operation.
+ *  <li>Iterators do not support the mutative {@code remove} operation.
  *  <li>Traversal via iterators is fast and cannot encounter
  *      interference from other threads. Iterators rely on
  *      unchanging snapshots of the array at the time the iterators were
  *      constructed.
  * </ul>
  *
- * <p> <b>Sample Usage.</b> The following code sketch uses a
+ * <p><b>Sample Usage.</b> The following code sketch uses a
  * copy-on-write set to maintain a set of Handler objects that
  * perform some action upon state updates.
  *
@@ -48,7 +48,7 @@
  *   public void update() {
  *     changeState();
  *     for (Handler handler : handlers)
- *        handler.handle();
+ *       handler.handle();
  *   }
  * }}</pre>
  *
@@ -92,22 +92,22 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains no elements.
+     * Returns {@code true} if this set contains no elements.
      *
-     * @return <tt>true</tt> if this set contains no elements
+     * @return {@code true} if this set contains no elements
      */
     public boolean isEmpty() {
         return al.isEmpty();
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this set
-     * contains an element <tt>e</tt> such that
+     * Returns {@code true} if this set contains the specified element.
+     * More formally, returns {@code true} if and only if this set
+     * contains an element {@code e} such that
      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
      *
      * @param o element whose presence in this set is to be tested
-     * @return <tt>true</tt> if this set contains the specified element
+     * @return {@code true} if this set contains the specified element
      */
     public boolean contains(Object o) {
         return al.contains(o);
@@ -143,7 +143,7 @@
      * <p>If this set fits in the specified array with room to spare
      * (i.e., the array has more elements than this set), the element in
      * the array immediately following the end of the set is set to
-     * <tt>null</tt>.  (This is useful in determining the length of this
+     * {@code null}.  (This is useful in determining the length of this
      * set <i>only</i> if the caller knows that this set does not contain
      * any null elements.)
      *
@@ -156,14 +156,14 @@
      * precise control over the runtime type of the output array, and may,
      * under certain circumstances, be used to save allocation costs.
      *
-     * <p>Suppose <tt>x</tt> is a set known to contain only strings.
+     * <p>Suppose {@code x} is a set known to contain only strings.
      * The following code can be used to dump the set into a newly allocated
-     * array of <tt>String</tt>:
+     * array of {@code String}:
      *
      *  <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
      *
-     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
-     * <tt>toArray()</tt>.
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
      *
      * @param a the array into which the elements of this set are to be
      *        stored, if it is big enough; otherwise, a new array of the same
@@ -188,15 +188,15 @@
 
     /**
      * Removes the specified element from this set if it is present.
-     * More formally, removes an element <tt>e</tt> such that
+     * More formally, removes an element {@code e} such that
      * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
-     * if this set contains such an element.  Returns <tt>true</tt> if
+     * if this set contains such an element.  Returns {@code true} if
      * this set contained the element (or equivalently, if this set
      * changed as a result of the call).  (This set will not contain the
      * element once the call returns.)
      *
      * @param o object to be removed from this set, if present
-     * @return <tt>true</tt> if this set contained the specified element
+     * @return {@code true} if this set contained the specified element
      */
     public boolean remove(Object o) {
         return al.remove(o);
@@ -204,14 +204,14 @@
 
     /**
      * Adds the specified element to this set if it is not already present.
-     * More formally, adds the specified element <tt>e</tt> to this set if
-     * the set contains no element <tt>e2</tt> such that
+     * More formally, adds the specified element {@code e} to this set if
+     * the set contains no element {@code e2} such that
      * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
      * If this set already contains the element, the call leaves the set
-     * unchanged and returns <tt>false</tt>.
+     * unchanged and returns {@code false}.
      *
      * @param e element to be added to this set
-     * @return <tt>true</tt> if this set did not already contain the specified
+     * @return {@code true} if this set did not already contain the specified
      *         element
      */
     public boolean add(E e) {
@@ -219,12 +219,12 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this set contains all of the elements of the
+     * Returns {@code true} if this set contains all of the elements of the
      * specified collection.  If the specified collection is also a set, this
-     * method returns <tt>true</tt> if it is a <i>subset</i> of this set.
+     * method returns {@code true} if it is a <i>subset</i> of this set.
      *
      * @param  c collection to be checked for containment in this set
-     * @return <tt>true</tt> if this set contains all of the elements of the
+     * @return {@code true} if this set contains all of the elements of the
      *         specified collection
      * @throws NullPointerException if the specified collection is null
      * @see #contains(Object)
@@ -236,13 +236,13 @@
     /**
      * Adds all of the elements in the specified collection to this set if
      * they're not already present.  If the specified collection is also a
-     * set, the <tt>addAll</tt> operation effectively modifies this set so
+     * set, the {@code addAll} operation effectively modifies this set so
      * that its value is the <i>union</i> of the two sets.  The behavior of
      * this operation is undefined if the specified collection is modified
      * while the operation is in progress.
      *
      * @param  c collection containing elements to be added to this set
-     * @return <tt>true</tt> if this set changed as a result of the call
+     * @return {@code true} if this set changed as a result of the call
      * @throws NullPointerException if the specified collection is null
      * @see #add(Object)
      */
@@ -257,7 +257,7 @@
      * <i>asymmetric set difference</i> of the two sets.
      *
      * @param  c collection containing elements to be removed from this set
-     * @return <tt>true</tt> if this set changed as a result of the call
+     * @return {@code true} if this set changed as a result of the call
      * @throws ClassCastException if the class of an element of this set
      *         is incompatible with the specified collection (optional)
      * @throws NullPointerException if this set contains a null element and the
@@ -278,7 +278,7 @@
      * two sets.
      *
      * @param  c collection containing elements to be retained in this set
-     * @return <tt>true</tt> if this set changed as a result of the call
+     * @return {@code true} if this set changed as a result of the call
      * @throws ClassCastException if the class of an element of this set
      *         is incompatible with the specified collection (optional)
      * @throws NullPointerException if this set contains a null element and the
@@ -297,7 +297,7 @@
      * <p>The returned iterator provides a snapshot of the state of the set
      * when the iterator was constructed. No synchronization is needed while
      * traversing the iterator. The iterator does <em>NOT</em> support the
-     * <tt>remove</tt> method.
+     * {@code remove} method.
      *
      * @return an iterator over the elements in this set
      */
@@ -354,7 +354,7 @@
     }
 
     /**
-     * Test for equality, coping with nulls.
+     * Tests for equality, coping with nulls.
      */
     private static boolean eq(Object o1, Object o2) {
         return (o1 == null) ? o2 == null : o1.equals(o2);
diff --git a/luni/src/main/java/java/util/concurrent/CountDownLatch.java b/luni/src/main/java/java/util/concurrent/CountDownLatch.java
index e90badf..fe0fa65 100644
--- a/luni/src/main/java/java/util/concurrent/CountDownLatch.java
+++ b/luni/src/main/java/java/util/concurrent/CountDownLatch.java
@@ -5,7 +5,7 @@
  */
 
 package java.util.concurrent;
-import java.util.concurrent.locks.*;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
 
 /**
  * A synchronization aid that allows one or more threads to wait until
@@ -63,15 +63,15 @@
  *   private final CountDownLatch startSignal;
  *   private final CountDownLatch doneSignal;
  *   Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
- *      this.startSignal = startSignal;
- *      this.doneSignal = doneSignal;
+ *     this.startSignal = startSignal;
+ *     this.doneSignal = doneSignal;
  *   }
  *   public void run() {
- *      try {
- *        startSignal.await();
- *        doWork();
- *        doneSignal.countDown();
- *      } catch (InterruptedException ex) {} // return;
+ *     try {
+ *       startSignal.await();
+ *       doWork();
+ *       doneSignal.countDown();
+ *     } catch (InterruptedException ex) {} // return;
  *   }
  *
  *   void doWork() { ... }
@@ -101,14 +101,14 @@
  *   private final CountDownLatch doneSignal;
  *   private final int i;
  *   WorkerRunnable(CountDownLatch doneSignal, int i) {
- *      this.doneSignal = doneSignal;
- *      this.i = i;
+ *     this.doneSignal = doneSignal;
+ *     this.i = i;
  *   }
  *   public void run() {
- *      try {
- *        doWork(i);
- *        doneSignal.countDown();
- *      } catch (InterruptedException ex) {} // return;
+ *     try {
+ *       doWork(i);
+ *       doneSignal.countDown();
+ *     } catch (InterruptedException ex) {} // return;
  *   }
  *
  *   void doWork() { ... }
diff --git a/luni/src/main/java/java/util/concurrent/CountedCompleter.java b/luni/src/main/java/java/util/concurrent/CountedCompleter.java
new file mode 100644
index 0000000..ffe7582
--- /dev/null
+++ b/luni/src/main/java/java/util/concurrent/CountedCompleter.java
@@ -0,0 +1,715 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * A {@link ForkJoinTask} with a completion action performed when
+ * triggered and there are no remaining pending
+ * actions. CountedCompleters are in general more robust in the
+ * presence of subtask stalls and blockage than are other forms of
+ * ForkJoinTasks, but are less intuitive to program.  Uses of
+ * CountedCompleter are similar to those of other completion based
+ * components (such as {@link java.nio.channels.CompletionHandler})
+ * except that multiple <em>pending</em> completions may be necessary
+ * to trigger the completion action {@link #onCompletion}, not just one.
+ * Unless initialized otherwise, the {@linkplain #getPendingCount pending
+ * count} starts at zero, but may be (atomically) changed using
+ * methods {@link #setPendingCount}, {@link #addToPendingCount}, and
+ * {@link #compareAndSetPendingCount}. Upon invocation of {@link
+ * #tryComplete}, if the pending action count is nonzero, it is
+ * decremented; otherwise, the completion action is performed, and if
+ * this completer itself has a completer, the process is continued
+ * with its completer.  As is the case with related synchronization
+ * components such as {@link java.util.concurrent.Phaser Phaser} and
+ * {@link java.util.concurrent.Semaphore Semaphore}, these methods
+ * affect only internal counts; they do not establish any further
+ * internal bookkeeping. In particular, the identities of pending
+ * tasks are not maintained. As illustrated below, you can create
+ * subclasses that do record some or all pending tasks or their
+ * results when needed.  As illustrated below, utility methods
+ * supporting customization of completion traversals are also
+ * provided. However, because CountedCompleters provide only basic
+ * synchronization mechanisms, it may be useful to create further
+ * abstract subclasses that maintain linkages, fields, and additional
+ * support methods appropriate for a set of related usages.
+ *
+ * <p>A concrete CountedCompleter class must define method {@link
+ * #compute}, that should in most cases (as illustrated below), invoke
+ * {@code tryComplete()} once before returning. The class may also
+ * optionally override method {@link #onCompletion} to perform an
+ * action upon normal completion, and method {@link
+ * #onExceptionalCompletion} to perform an action upon any exception.
+ *
+ * <p>CountedCompleters most often do not bear results, in which case
+ * they are normally declared as {@code CountedCompleter<Void>}, and
+ * will always return {@code null} as a result value.  In other cases,
+ * you should override method {@link #getRawResult} to provide a
+ * result from {@code join(), invoke()}, and related methods.  In
+ * general, this method should return the value of a field (or a
+ * function of one or more fields) of the CountedCompleter object that
+ * holds the result upon completion. Method {@link #setRawResult} by
+ * default plays no role in CountedCompleters.  It is possible, but
+ * rarely applicable, to override this method to maintain other
+ * objects or fields holding result data.
+ *
+ * <p>A CountedCompleter that does not itself have a completer (i.e.,
+ * one for which {@link #getCompleter} returns {@code null}) can be
+ * used as a regular ForkJoinTask with this added functionality.
+ * However, any completer that in turn has another completer serves
+ * only as an internal helper for other computations, so its own task
+ * status (as reported in methods such as {@link ForkJoinTask#isDone})
+ * is arbitrary; this status changes only upon explicit invocations of
+ * {@link #complete}, {@link ForkJoinTask#cancel}, {@link
+ * ForkJoinTask#completeExceptionally} or upon exceptional completion
+ * of method {@code compute}. Upon any exceptional completion, the
+ * exception may be relayed to a task's completer (and its completer,
+ * and so on), if one exists and it has not otherwise already
+ * completed. Similarly, cancelling an internal CountedCompleter has
+ * only a local effect on that completer, so is not often useful.
+ *
+ * <p><b>Sample Usages.</b>
+ *
+ * <p><b>Parallel recursive decomposition.</b> CountedCompleters may
+ * be arranged in trees similar to those often used with {@link
+ * RecursiveAction}s, although the constructions involved in setting
+ * them up typically vary. Here, the completer of each task is its
+ * parent in the computation tree. Even though they entail a bit more
+ * bookkeeping, CountedCompleters may be better choices when applying
+ * a possibly time-consuming operation (that cannot be further
+ * subdivided) to each element of an array or collection; especially
+ * when the operation takes a significantly different amount of time
+ * to complete for some elements than others, either because of
+ * intrinsic variation (for example I/O) or auxiliary effects such as
+ * garbage collection.  Because CountedCompleters provide their own
+ * continuations, other threads need not block waiting to perform
+ * them.
+ *
+ * <p>For example, here is an initial version of a class that uses
+ * divide-by-two recursive decomposition to divide work into single
+ * pieces (leaf tasks). Even when work is split into individual calls,
+ * tree-based techniques are usually preferable to directly forking
+ * leaf tasks, because they reduce inter-thread communication and
+ * improve load balancing. In the recursive case, the second of each
+ * pair of subtasks to finish triggers completion of its parent
+ * (because no result combination is performed, the default no-op
+ * implementation of method {@code onCompletion} is not overridden). A
+ * static utility method sets up the base task and invokes it
+ * (here, implicitly using the {@link ForkJoinPool#commonPool()}).
+ *
+ * <pre> {@code
+ * class MyOperation<E> { void apply(E e) { ... }  }
+ *
+ * class ForEach<E> extends CountedCompleter<Void> {
+ *
+ *   public static <E> void forEach(E[] array, MyOperation<E> op) {
+ *     new ForEach<E>(null, array, op, 0, array.length).invoke();
+ *   }
+ *
+ *   final E[] array; final MyOperation<E> op; final int lo, hi;
+ *   ForEach(CountedCompleter<?> p, E[] array, MyOperation<E> op, int lo, int hi) {
+ *     super(p);
+ *     this.array = array; this.op = op; this.lo = lo; this.hi = hi;
+ *   }
+ *
+ *   public void compute() { // version 1
+ *     if (hi - lo >= 2) {
+ *       int mid = (lo + hi) >>> 1;
+ *       setPendingCount(2); // must set pending count before fork
+ *       new ForEach(this, array, op, mid, hi).fork(); // right child
+ *       new ForEach(this, array, op, lo, mid).fork(); // left child
+ *     }
+ *     else if (hi > lo)
+ *       op.apply(array[lo]);
+ *     tryComplete();
+ *   }
+ * }}</pre>
+ *
+ * This design can be improved by noticing that in the recursive case,
+ * the task has nothing to do after forking its right task, so can
+ * directly invoke its left task before returning. (This is an analog
+ * of tail recursion removal.)  Also, because the task returns upon
+ * executing its left task (rather than falling through to invoke
+ * {@code tryComplete}) the pending count is set to one:
+ *
+ * <pre> {@code
+ * class ForEach<E> ...
+ *   public void compute() { // version 2
+ *     if (hi - lo >= 2) {
+ *       int mid = (lo + hi) >>> 1;
+ *       setPendingCount(1); // only one pending
+ *       new ForEach(this, array, op, mid, hi).fork(); // right child
+ *       new ForEach(this, array, op, lo, mid).compute(); // direct invoke
+ *     }
+ *     else {
+ *       if (hi > lo)
+ *         op.apply(array[lo]);
+ *       tryComplete();
+ *     }
+ *   }
+ * }</pre>
+ *
+ * As a further improvement, notice that the left task need not even
+ * exist.  Instead of creating a new one, we can iterate using the
+ * original task, and add a pending count for each fork. Additionally,
+ * because no task in this tree implements an {@link #onCompletion}
+ * method, {@code tryComplete()} can be replaced with {@link
+ * #propagateCompletion}.
+ *
+ * <pre> {@code
+ * class ForEach<E> ...
+ *   public void compute() { // version 3
+ *     int l = lo,  h = hi;
+ *     while (h - l >= 2) {
+ *       int mid = (l + h) >>> 1;
+ *       addToPendingCount(1);
+ *       new ForEach(this, array, op, mid, h).fork(); // right child
+ *       h = mid;
+ *     }
+ *     if (h > l)
+ *       op.apply(array[l]);
+ *     propagateCompletion();
+ *   }
+ * }</pre>
+ *
+ * Additional improvements of such classes might entail precomputing
+ * pending counts so that they can be established in constructors,
+ * specializing classes for leaf steps, subdividing by say, four,
+ * instead of two per iteration, and using an adaptive threshold
+ * instead of always subdividing down to single elements.
+ *
+ * <p><b>Searching.</b> A tree of CountedCompleters can search for a
+ * value or property in different parts of a data structure, and
+ * report a result in an {@link
+ * java.util.concurrent.atomic.AtomicReference AtomicReference} as
+ * soon as one is found. The others can poll the result to avoid
+ * unnecessary work. (You could additionally {@linkplain #cancel
+ * cancel} other tasks, but it is usually simpler and more efficient
+ * to just let them notice that the result is set and if so skip
+ * further processing.)  Illustrating again with an array using full
+ * partitioning (again, in practice, leaf tasks will almost always
+ * process more than one element):
+ *
+ * <pre> {@code
+ * class Searcher<E> extends CountedCompleter<E> {
+ *   final E[] array; final AtomicReference<E> result; final int lo, hi;
+ *   Searcher(CountedCompleter<?> p, E[] array, AtomicReference<E> result, int lo, int hi) {
+ *     super(p);
+ *     this.array = array; this.result = result; this.lo = lo; this.hi = hi;
+ *   }
+ *   public E getRawResult() { return result.get(); }
+ *   public void compute() { // similar to ForEach version 3
+ *     int l = lo,  h = hi;
+ *     while (result.get() == null && h >= l) {
+ *       if (h - l >= 2) {
+ *         int mid = (l + h) >>> 1;
+ *         addToPendingCount(1);
+ *         new Searcher(this, array, result, mid, h).fork();
+ *         h = mid;
+ *       }
+ *       else {
+ *         E x = array[l];
+ *         if (matches(x) && result.compareAndSet(null, x))
+ *           quietlyCompleteRoot(); // root task is now joinable
+ *         break;
+ *       }
+ *     }
+ *     tryComplete(); // normally complete whether or not found
+ *   }
+ *   boolean matches(E e) { ... } // return true if found
+ *
+ *   public static <E> E search(E[] array) {
+ *       return new Searcher<E>(null, array, new AtomicReference<E>(), 0, array.length).invoke();
+ *   }
+ * }}</pre>
+ *
+ * In this example, as well as others in which tasks have no other
+ * effects except to compareAndSet a common result, the trailing
+ * unconditional invocation of {@code tryComplete} could be made
+ * conditional ({@code if (result.get() == null) tryComplete();})
+ * because no further bookkeeping is required to manage completions
+ * once the root task completes.
+ *
+ * <p><b>Recording subtasks.</b> CountedCompleter tasks that combine
+ * results of multiple subtasks usually need to access these results
+ * in method {@link #onCompletion}. As illustrated in the following
+ * class (that performs a simplified form of map-reduce where mappings
+ * and reductions are all of type {@code E}), one way to do this in
+ * divide and conquer designs is to have each subtask record its
+ * sibling, so that it can be accessed in method {@code onCompletion}.
+ * This technique applies to reductions in which the order of
+ * combining left and right results does not matter; ordered
+ * reductions require explicit left/right designations.  Variants of
+ * other streamlinings seen in the above examples may also apply.
+ *
+ * <pre> {@code
+ * class MyMapper<E> { E apply(E v) {  ...  } }
+ * class MyReducer<E> { E apply(E x, E y) {  ...  } }
+ * class MapReducer<E> extends CountedCompleter<E> {
+ *   final E[] array; final MyMapper<E> mapper;
+ *   final MyReducer<E> reducer; final int lo, hi;
+ *   MapReducer<E> sibling;
+ *   E result;
+ *   MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
+ *              MyReducer<E> reducer, int lo, int hi) {
+ *     super(p);
+ *     this.array = array; this.mapper = mapper;
+ *     this.reducer = reducer; this.lo = lo; this.hi = hi;
+ *   }
+ *   public void compute() {
+ *     if (hi - lo >= 2) {
+ *       int mid = (lo + hi) >>> 1;
+ *       MapReducer<E> left = new MapReducer(this, array, mapper, reducer, lo, mid);
+ *       MapReducer<E> right = new MapReducer(this, array, mapper, reducer, mid, hi);
+ *       left.sibling = right;
+ *       right.sibling = left;
+ *       setPendingCount(1); // only right is pending
+ *       right.fork();
+ *       left.compute();     // directly execute left
+ *     }
+ *     else {
+ *       if (hi > lo)
+ *           result = mapper.apply(array[lo]);
+ *       tryComplete();
+ *     }
+ *   }
+ *   public void onCompletion(CountedCompleter<?> caller) {
+ *     if (caller != this) {
+ *       MapReducer<E> child = (MapReducer<E>)caller;
+ *       MapReducer<E> sib = child.sibling;
+ *       if (sib == null || sib.result == null)
+ *         result = child.result;
+ *       else
+ *         result = reducer.apply(child.result, sib.result);
+ *     }
+ *   }
+ *   public E getRawResult() { return result; }
+ *
+ *   public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
+ *     return new MapReducer<E>(null, array, mapper, reducer,
+ *                              0, array.length).invoke();
+ *   }
+ * }}</pre>
+ *
+ * Here, method {@code onCompletion} takes a form common to many
+ * completion designs that combine results. This callback-style method
+ * is triggered once per task, in either of the two different contexts
+ * in which the pending count is, or becomes, zero: (1) by a task
+ * itself, if its pending count is zero upon invocation of {@code
+ * tryComplete}, or (2) by any of its subtasks when they complete and
+ * decrement the pending count to zero. The {@code caller} argument
+ * distinguishes cases.  Most often, when the caller is {@code this},
+ * no action is necessary. Otherwise the caller argument can be used
+ * (usually via a cast) to supply a value (and/or links to other
+ * values) to be combined.  Assuming proper use of pending counts, the
+ * actions inside {@code onCompletion} occur (once) upon completion of
+ * a task and its subtasks. No additional synchronization is required
+ * within this method to ensure thread safety of accesses to fields of
+ * this task or other completed tasks.
+ *
+ * <p><b>Completion Traversals</b>. If using {@code onCompletion} to
+ * process completions is inapplicable or inconvenient, you can use
+ * methods {@link #firstComplete} and {@link #nextComplete} to create
+ * custom traversals.  For example, to define a MapReducer that only
+ * splits out right-hand tasks in the form of the third ForEach
+ * example, the completions must cooperatively reduce along
+ * unexhausted subtask links, which can be done as follows:
+ *
+ * <pre> {@code
+ * class MapReducer<E> extends CountedCompleter<E> { // version 2
+ *   final E[] array; final MyMapper<E> mapper;
+ *   final MyReducer<E> reducer; final int lo, hi;
+ *   MapReducer<E> forks, next; // record subtask forks in list
+ *   E result;
+ *   MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
+ *              MyReducer<E> reducer, int lo, int hi, MapReducer<E> next) {
+ *     super(p);
+ *     this.array = array; this.mapper = mapper;
+ *     this.reducer = reducer; this.lo = lo; this.hi = hi;
+ *     this.next = next;
+ *   }
+ *   public void compute() {
+ *     int l = lo,  h = hi;
+ *     while (h - l >= 2) {
+ *       int mid = (l + h) >>> 1;
+ *       addToPendingCount(1);
+ *       (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork();
+ *       h = mid;
+ *     }
+ *     if (h > l)
+ *       result = mapper.apply(array[l]);
+ *     // process completions by reducing along and advancing subtask links
+ *     for (CountedCompleter<?> c = firstComplete(); c != null; c = c.nextComplete()) {
+ *       for (MapReducer t = (MapReducer)c, s = t.forks;  s != null; s = t.forks = s.next)
+ *         t.result = reducer.apply(t.result, s.result);
+ *     }
+ *   }
+ *   public E getRawResult() { return result; }
+ *
+ *   public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
+ *     return new MapReducer<E>(null, array, mapper, reducer,
+ *                              0, array.length, null).invoke();
+ *   }
+ * }}</pre>
+ *
+ * <p><b>Triggers.</b> Some CountedCompleters are themselves never
+ * forked, but instead serve as bits of plumbing in other designs;
+ * including those in which the completion of one of more async tasks
+ * triggers another async task. For example:
+ *
+ * <pre> {@code
+ * class HeaderBuilder extends CountedCompleter<...> { ... }
+ * class BodyBuilder extends CountedCompleter<...> { ... }
+ * class PacketSender extends CountedCompleter<...> {
+ *   PacketSender(...) { super(null, 1); ... } // trigger on second completion
+ *   public void compute() { } // never called
+ *   public void onCompletion(CountedCompleter<?> caller) { sendPacket(); }
+ * }
+ * // sample use:
+ * PacketSender p = new PacketSender();
+ * new HeaderBuilder(p, ...).fork();
+ * new BodyBuilder(p, ...).fork();
+ * }</pre>
+ *
+ * @since 1.8
+ * @hide
+ * @author Doug Lea
+ */
+public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
+    private static final long serialVersionUID = 5232453752276485070L;
+
+    /** This task's completer, or null if none */
+    final CountedCompleter<?> completer;
+    /** The number of pending tasks until completion */
+    volatile int pending;
+
+    /**
+     * Creates a new CountedCompleter with the given completer
+     * and initial pending count.
+     *
+     * @param completer this task's completer, or {@code null} if none
+     * @param initialPendingCount the initial pending count
+     */
+    protected CountedCompleter(CountedCompleter<?> completer,
+                               int initialPendingCount) {
+        this.completer = completer;
+        this.pending = initialPendingCount;
+    }
+
+    /**
+     * Creates a new CountedCompleter with the given completer
+     * and an initial pending count of zero.
+     *
+     * @param completer this task's completer, or {@code null} if none
+     */
+    protected CountedCompleter(CountedCompleter<?> completer) {
+        this.completer = completer;
+    }
+
+    /**
+     * Creates a new CountedCompleter with no completer
+     * and an initial pending count of zero.
+     */
+    protected CountedCompleter() {
+        this.completer = null;
+    }
+
+    /**
+     * The main computation performed by this task.
+     */
+    public abstract void compute();
+
+    /**
+     * Performs an action when method {@link #tryComplete} is invoked
+     * and the pending count is zero, or when the unconditional
+     * method {@link #complete} is invoked.  By default, this method
+     * does nothing. You can distinguish cases by checking the
+     * identity of the given caller argument. If not equal to {@code
+     * this}, then it is typically a subtask that may contain results
+     * (and/or links to other results) to combine.
+     *
+     * @param caller the task invoking this method (which may
+     * be this task itself)
+     */
+    public void onCompletion(CountedCompleter<?> caller) {
+    }
+
+    /**
+     * Performs an action when method {@link #completeExceptionally}
+     * is invoked or method {@link #compute} throws an exception, and
+     * this task has not otherwise already completed normally. On
+     * entry to this method, this task {@link
+     * ForkJoinTask#isCompletedAbnormally}.  The return value of this
+     * method controls further propagation: If {@code true} and this
+     * task has a completer, then this completer is also completed
+     * exceptionally.  The default implementation of this method does
+     * nothing except return {@code true}.
+     *
+     * @param ex the exception
+     * @param caller the task invoking this method (which may
+     * be this task itself)
+     * @return true if this exception should be propagated to this
+     * task's completer, if one exists
+     */
+    public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller) {
+        return true;
+    }
+
+    /**
+     * Returns the completer established in this task's constructor,
+     * or {@code null} if none.
+     *
+     * @return the completer
+     */
+    public final CountedCompleter<?> getCompleter() {
+        return completer;
+    }
+
+    /**
+     * Returns the current pending count.
+     *
+     * @return the current pending count
+     */
+    public final int getPendingCount() {
+        return pending;
+    }
+
+    /**
+     * Sets the pending count to the given value.
+     *
+     * @param count the count
+     */
+    public final void setPendingCount(int count) {
+        pending = count;
+    }
+
+    /**
+     * Adds (atomically) the given value to the pending count.
+     *
+     * @param delta the value to add
+     */
+    public final void addToPendingCount(int delta) {
+        int c; // note: can replace with intrinsic in jdk8
+        do {} while (!U.compareAndSwapInt(this, PENDING, c = pending, c+delta));
+    }
+
+    /**
+     * Sets (atomically) the pending count to the given count only if
+     * it currently holds the given expected value.
+     *
+     * @param expected the expected value
+     * @param count the new value
+     * @return true if successful
+     */
+    public final boolean compareAndSetPendingCount(int expected, int count) {
+        return U.compareAndSwapInt(this, PENDING, expected, count);
+    }
+
+    /**
+     * If the pending count is nonzero, (atomically) decrements it.
+     *
+     * @return the initial (undecremented) pending count holding on entry
+     * to this method
+     */
+    public final int decrementPendingCountUnlessZero() {
+        int c;
+        do {} while ((c = pending) != 0 &&
+                     !U.compareAndSwapInt(this, PENDING, c, c - 1));
+        return c;
+    }
+
+    /**
+     * Returns the root of the current computation; i.e., this
+     * task if it has no completer, else its completer's root.
+     *
+     * @return the root of the current computation
+     */
+    public final CountedCompleter<?> getRoot() {
+        CountedCompleter<?> a = this, p;
+        while ((p = a.completer) != null)
+            a = p;
+        return a;
+    }
+
+    /**
+     * If the pending count is nonzero, decrements the count;
+     * otherwise invokes {@link #onCompletion} and then similarly
+     * tries to complete this task's completer, if one exists,
+     * else marks this task as complete.
+     */
+    public final void tryComplete() {
+        CountedCompleter<?> a = this, s = a;
+        for (int c;;) {
+            if ((c = a.pending) == 0) {
+                a.onCompletion(s);
+                if ((a = (s = a).completer) == null) {
+                    s.quietlyComplete();
+                    return;
+                }
+            }
+            else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
+                return;
+        }
+    }
+
+    /**
+     * Equivalent to {@link #tryComplete} but does not invoke {@link
+     * #onCompletion} along the completion path: If the pending count
+     * is nonzero, decrements the count; otherwise, similarly tries to
+     * complete this task's completer, if one exists, else marks this
+     * task as complete. This method may be useful in cases where
+     * {@code onCompletion} should not, or need not, be invoked for
+     * each completer in a computation.
+     */
+    public final void propagateCompletion() {
+        CountedCompleter<?> a = this, s = a;
+        for (int c;;) {
+            if ((c = a.pending) == 0) {
+                if ((a = (s = a).completer) == null) {
+                    s.quietlyComplete();
+                    return;
+                }
+            }
+            else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
+                return;
+        }
+    }
+
+    /**
+     * Regardless of pending count, invokes {@link #onCompletion},
+     * marks this task as complete and further triggers {@link
+     * #tryComplete} on this task's completer, if one exists.  The
+     * given rawResult is used as an argument to {@link #setRawResult}
+     * before invoking {@link #onCompletion} or marking this task as
+     * complete; its value is meaningful only for classes overriding
+     * {@code setRawResult}.
+     *
+     * <p>This method may be useful when forcing completion as soon as
+     * any one (versus all) of several subtask results are obtained.
+     * However, in the common (and recommended) case in which {@code
+     * setRawResult} is not overridden, this effect can be obtained
+     * more simply using {@code quietlyCompleteRoot();}.
+     *
+     * @param rawResult the raw result
+     */
+    public void complete(T rawResult) {
+        CountedCompleter<?> p;
+        setRawResult(rawResult);
+        onCompletion(this);
+        quietlyComplete();
+        if ((p = completer) != null)
+            p.tryComplete();
+    }
+
+
+    /**
+     * If this task's pending count is zero, returns this task;
+     * otherwise decrements its pending count and returns {@code
+     * null}. This method is designed to be used with {@link
+     * #nextComplete} in completion traversal loops.
+     *
+     * @return this task, if pending count was zero, else {@code null}
+     */
+    public final CountedCompleter<?> firstComplete() {
+        for (int c;;) {
+            if ((c = pending) == 0)
+                return this;
+            else if (U.compareAndSwapInt(this, PENDING, c, c - 1))
+                return null;
+        }
+    }
+
+    /**
+     * If this task does not have a completer, invokes {@link
+     * ForkJoinTask#quietlyComplete} and returns {@code null}.  Or, if
+     * the completer's pending count is non-zero, decrements that
+     * pending count and returns {@code null}.  Otherwise, returns the
+     * completer.  This method can be used as part of a completion
+     * traversal loop for homogeneous task hierarchies:
+     *
+     * <pre> {@code
+     * for (CountedCompleter<?> c = firstComplete();
+     *      c != null;
+     *      c = c.nextComplete()) {
+     *   // ... process c ...
+     * }}</pre>
+     *
+     * @return the completer, or {@code null} if none
+     */
+    public final CountedCompleter<?> nextComplete() {
+        CountedCompleter<?> p;
+        if ((p = completer) != null)
+            return p.firstComplete();
+        else {
+            quietlyComplete();
+            return null;
+        }
+    }
+
+    /**
+     * Equivalent to {@code getRoot().quietlyComplete()}.
+     */
+    public final void quietlyCompleteRoot() {
+        for (CountedCompleter<?> a = this, p;;) {
+            if ((p = a.completer) == null) {
+                a.quietlyComplete();
+                return;
+            }
+            a = p;
+        }
+    }
+
+    /**
+     * Supports ForkJoinTask exception propagation.
+     */
+    void internalPropagateException(Throwable ex) {
+        CountedCompleter<?> a = this, s = a;
+        while (a.onExceptionalCompletion(ex, s) &&
+               (a = (s = a).completer) != null && a.status >= 0)
+            a.recordExceptionalCompletion(ex);
+    }
+
+    /**
+     * Implements execution conventions for CountedCompleters.
+     */
+    protected final boolean exec() {
+        compute();
+        return false;
+    }
+
+    /**
+     * Returns the result of the computation. By default
+     * returns {@code null}, which is appropriate for {@code Void}
+     * actions, but in other cases should be overridden, almost
+     * always to return a field or function of a field that
+     * holds the result upon completion.
+     *
+     * @return the result of the computation
+     */
+    public T getRawResult() { return null; }
+
+    /**
+     * A method that result-bearing CountedCompleters may optionally
+     * use to help maintain result data.  By default, does nothing.
+     * Overrides are not recommended. However, if this method is
+     * overridden to update existing objects or fields, then it must
+     * in general be defined to be thread-safe.
+     */
+    protected void setRawResult(T t) { }
+
+    // Unsafe mechanics
+    private static final sun.misc.Unsafe U;
+    private static final long PENDING;
+    static {
+        try {
+            U = sun.misc.Unsafe.getUnsafe();
+            PENDING = U.objectFieldOffset
+                (CountedCompleter.class.getDeclaredField("pending"));
+        } catch (Exception e) {
+            throw new Error(e);
+        }
+    }
+}
diff --git a/luni/src/main/java/java/util/concurrent/CyclicBarrier.java b/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
index cf0b46e..e1a7bee 100644
--- a/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
+++ b/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
@@ -5,7 +5,8 @@
  */
 
 package java.util.concurrent;
-import java.util.concurrent.locks.*;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * A synchronization aid that allows a set of threads to all wait for
@@ -15,7 +16,7 @@
  * <em>cyclic</em> because it can be re-used after the waiting threads
  * are released.
  *
- * <p>A <tt>CyclicBarrier</tt> supports an optional {@link Runnable} command
+ * <p>A {@code CyclicBarrier} supports an optional {@link Runnable} command
  * that is run once per barrier point, after the last thread in the party
  * arrives, but before any threads are released.
  * This <em>barrier action</em> is useful
@@ -68,8 +69,8 @@
  * barrier until all rows have been processed. When all rows are processed
  * the supplied {@link Runnable} barrier action is executed and merges the
  * rows. If the merger
- * determines that a solution has been found then <tt>done()</tt> will return
- * <tt>true</tt> and each worker will terminate.
+ * determines that a solution has been found then {@code done()} will return
+ * {@code true} and each worker will terminate.
  *
  * <p>If the barrier action does not rely on the parties being suspended when
  * it is executed, then any of the threads in the party could execute that
@@ -82,7 +83,7 @@
  *   // log the completion of this iteration
  * }}</pre>
  *
- * <p>The <tt>CyclicBarrier</tt> uses an all-or-none breakage model
+ * <p>The {@code CyclicBarrier} uses an all-or-none breakage model
  * for failed synchronization attempts: If a thread leaves a barrier
  * point prematurely because of interruption, failure, or timeout, all
  * other threads waiting at that barrier point will also leave
@@ -109,7 +110,7 @@
      * is reset. There can be many generations associated with threads
      * using the barrier - due to the non-deterministic way the lock
      * may be allocated to waiting threads - but only one of these
-     * can be active at a time (the one to which <tt>count</tt> applies)
+     * can be active at a time (the one to which {@code count} applies)
      * and all the rest are either broken or tripped.
      * There need not be an active generation if there has been a break
      * but no subsequent reset.
@@ -229,7 +230,7 @@
     }
 
     /**
-     * Creates a new <tt>CyclicBarrier</tt> that will trip when the
+     * Creates a new {@code CyclicBarrier} that will trip when the
      * given number of parties (threads) are waiting upon it, and which
      * will execute the given barrier action when the barrier is tripped,
      * performed by the last thread entering the barrier.
@@ -248,7 +249,7 @@
     }
 
     /**
-     * Creates a new <tt>CyclicBarrier</tt> that will trip when the
+     * Creates a new {@code CyclicBarrier} that will trip when the
      * given number of parties (threads) are waiting upon it, and
      * does not perform a predefined action when the barrier is tripped.
      *
@@ -271,7 +272,7 @@
 
     /**
      * Waits until all {@linkplain #getParties parties} have invoked
-     * <tt>await</tt> on this barrier.
+     * {@code await} on this barrier.
      *
      * <p>If the current thread is not the last to arrive then it is
      * disabled for thread scheduling purposes and lies dormant until
@@ -296,7 +297,7 @@
      *
      * <p>If the barrier is {@link #reset} while any thread is waiting,
      * or if the barrier {@linkplain #isBroken is broken} when
-     * <tt>await</tt> is invoked, or while any thread is waiting, then
+     * {@code await} is invoked, or while any thread is waiting, then
      * {@link BrokenBarrierException} is thrown.
      *
      * <p>If any thread is {@linkplain Thread#interrupt interrupted} while waiting,
@@ -313,7 +314,7 @@
      * the broken state.
      *
      * @return the arrival index of the current thread, where index
-     *         <tt>{@link #getParties()} - 1</tt> indicates the first
+     *         {@code getParties() - 1} indicates the first
      *         to arrive and zero indicates the last to arrive
      * @throws InterruptedException if the current thread was interrupted
      *         while waiting
@@ -321,7 +322,7 @@
      *         interrupted or timed out while the current thread was
      *         waiting, or the barrier was reset, or the barrier was
      *         broken when {@code await} was called, or the barrier
-     *         action (if present) failed due an exception.
+     *         action (if present) failed due to an exception
      */
     public int await() throws InterruptedException, BrokenBarrierException {
         try {
@@ -333,7 +334,7 @@
 
     /**
      * Waits until all {@linkplain #getParties parties} have invoked
-     * <tt>await</tt> on this barrier, or the specified waiting time elapses.
+     * {@code await} on this barrier, or the specified waiting time elapses.
      *
      * <p>If the current thread is not the last to arrive then it is
      * disabled for thread scheduling purposes and lies dormant until
@@ -363,7 +364,7 @@
      *
      * <p>If the barrier is {@link #reset} while any thread is waiting,
      * or if the barrier {@linkplain #isBroken is broken} when
-     * <tt>await</tt> is invoked, or while any thread is waiting, then
+     * {@code await} is invoked, or while any thread is waiting, then
      * {@link BrokenBarrierException} is thrown.
      *
      * <p>If any thread is {@linkplain Thread#interrupt interrupted} while
@@ -382,7 +383,7 @@
      * @param timeout the time to wait for the barrier
      * @param unit the time unit of the timeout parameter
      * @return the arrival index of the current thread, where index
-     *         <tt>{@link #getParties()} - 1</tt> indicates the first
+     *         {@code getParties() - 1} indicates the first
      *         to arrive and zero indicates the last to arrive
      * @throws InterruptedException if the current thread was interrupted
      *         while waiting
@@ -391,7 +392,7 @@
      *         interrupted or timed out while the current thread was
      *         waiting, or the barrier was reset, or the barrier was broken
      *         when {@code await} was called, or the barrier action (if
-     *         present) failed due an exception
+     *         present) failed due to an exception
      */
     public int await(long timeout, TimeUnit unit)
         throws InterruptedException,
diff --git a/luni/src/main/java/java/util/concurrent/DelayQueue.java b/luni/src/main/java/java/util/concurrent/DelayQueue.java
index 52028cb..945249e 100644
--- a/luni/src/main/java/java/util/concurrent/DelayQueue.java
+++ b/luni/src/main/java/java/util/concurrent/DelayQueue.java
@@ -4,7 +4,6 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
-
 package java.util.concurrent;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 import java.util.concurrent.locks.Condition;
@@ -17,15 +16,15 @@
 
 /**
  * An unbounded {@linkplain BlockingQueue blocking queue} of
- * <tt>Delayed</tt> elements, in which an element can only be taken
+ * {@code Delayed} elements, in which an element can only be taken
  * when its delay has expired.  The <em>head</em> of the queue is that
- * <tt>Delayed</tt> element whose delay expired furthest in the
- * past.  If no delay has expired there is no head and <tt>poll</tt>
- * will return <tt>null</tt>. Expiration occurs when an element's
- * <tt>getDelay(TimeUnit.NANOSECONDS)</tt> method returns a value less
+ * {@code Delayed} element whose delay expired furthest in the
+ * past.  If no delay has expired there is no head and {@code poll}
+ * will return {@code null}. Expiration occurs when an element's
+ * {@code getDelay(TimeUnit.NANOSECONDS)} method returns a value less
  * than or equal to zero.  Even though unexpired elements cannot be
- * removed using <tt>take</tt> or <tt>poll</tt>, they are otherwise
- * treated as normal elements. For example, the <tt>size</tt> method
+ * removed using {@code take} or {@code poll}, they are otherwise
+ * treated as normal elements. For example, the {@code size} method
  * returns the count of both expired and unexpired elements.
  * This queue does not permit null elements.
  *
@@ -39,11 +38,10 @@
  * @author Doug Lea
  * @param <E> the type of elements held in this collection
  */
-
 public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
     implements BlockingQueue<E> {
 
-    private transient final ReentrantLock lock = new ReentrantLock();
+    private final transient ReentrantLock lock = new ReentrantLock();
     private final PriorityQueue<E> q = new PriorityQueue<E>();
 
     /**
@@ -72,12 +70,12 @@
     private final Condition available = lock.newCondition();
 
     /**
-     * Creates a new <tt>DelayQueue</tt> that is initially empty.
+     * Creates a new {@code DelayQueue} that is initially empty.
      */
     public DelayQueue() {}
 
     /**
-     * Creates a <tt>DelayQueue</tt> initially containing the elements of the
+     * Creates a {@code DelayQueue} initially containing the elements of the
      * given collection of {@link Delayed} instances.
      *
      * @param c the collection of elements to initially contain
@@ -92,7 +90,7 @@
      * Inserts the specified element into this delay queue.
      *
      * @param e the element to add
-     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @return {@code true} (as specified by {@link Collection#add})
      * @throws NullPointerException if the specified element is null
      */
     public boolean add(E e) {
@@ -103,7 +101,7 @@
      * Inserts the specified element into this delay queue.
      *
      * @param e the element to add
-     * @return <tt>true</tt>
+     * @return {@code true}
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
@@ -139,7 +137,7 @@
      * @param e the element to add
      * @param timeout This parameter is ignored as the method never blocks
      * @param unit This parameter is ignored as the method never blocks
-     * @return <tt>true</tt>
+     * @return {@code true}
      * @throws NullPointerException {@inheritDoc}
      */
     public boolean offer(E e, long timeout, TimeUnit unit) {
@@ -147,10 +145,10 @@
     }
 
     /**
-     * Retrieves and removes the head of this queue, or returns <tt>null</tt>
+     * Retrieves and removes the head of this queue, or returns {@code null}
      * if this queue has no elements with an expired delay.
      *
-     * @return the head of this queue, or <tt>null</tt> if this
+     * @return the head of this queue, or {@code null} if this
      *         queue has no elements with an expired delay
      */
     public E poll() {
@@ -186,7 +184,8 @@
                     long delay = first.getDelay(NANOSECONDS);
                     if (delay <= 0)
                         return q.poll();
-                    else if (leader != null)
+                    first = null; // don't retain ref while waiting
+                    if (leader != null)
                         available.await();
                     else {
                         Thread thisThread = Thread.currentThread();
@@ -212,7 +211,7 @@
      * until an element with an expired delay is available on this queue,
      * or the specified wait time expires.
      *
-     * @return the head of this queue, or <tt>null</tt> if the
+     * @return the head of this queue, or {@code null} if the
      *         specified waiting time elapses before an element with
      *         an expired delay becomes available
      * @throws InterruptedException {@inheritDoc}
@@ -235,6 +234,7 @@
                         return q.poll();
                     if (nanos <= 0)
                         return null;
+                    first = null; // don't retain ref while waiting
                     if (nanos < delay || leader != null)
                         nanos = available.awaitNanos(nanos);
                     else {
@@ -259,13 +259,13 @@
 
     /**
      * Retrieves, but does not remove, the head of this queue, or
-     * returns <tt>null</tt> if this queue is empty.  Unlike
-     * <tt>poll</tt>, if no expired elements are available in the queue,
+     * returns {@code null} if this queue is empty.  Unlike
+     * {@code poll}, if no expired elements are available in the queue,
      * this method returns the element that will expire next,
      * if one exists.
      *
-     * @return the head of this queue, or <tt>null</tt> if this
-     *         queue is empty.
+     * @return the head of this queue, or {@code null} if this
+     *         queue is empty
      */
     public E peek() {
         final ReentrantLock lock = this.lock;
@@ -288,7 +288,7 @@
     }
 
     /**
-     * Return first element only if it is expired.
+     * Returns first element only if it is expired.
      * Used only by drainTo.  Call only when holding lock.
      */
     private E peekExpired() {
@@ -369,10 +369,10 @@
     }
 
     /**
-     * Always returns <tt>Integer.MAX_VALUE</tt> because
-     * a <tt>DelayQueue</tt> is not capacity constrained.
+     * Always returns {@code Integer.MAX_VALUE} because
+     * a {@code DelayQueue} is not capacity constrained.
      *
-     * @return <tt>Integer.MAX_VALUE</tt>
+     * @return {@code Integer.MAX_VALUE}
      */
     public int remainingCapacity() {
         return Integer.MAX_VALUE;
@@ -412,7 +412,7 @@
      * <p>If this queue fits in the specified array with room to spare
      * (i.e., the array has more elements than this queue), the element in
      * the array immediately following the end of the queue is set to
-     * <tt>null</tt>.
+     * {@code null}.
      *
      * <p>Like the {@link #toArray()} method, this method acts as bridge between
      * array-based and collection-based APIs.  Further, this method allows
@@ -420,12 +420,12 @@
      * under certain circumstances, be used to save allocation costs.
      *
      * <p>The following code can be used to dump a delay queue into a newly
-     * allocated array of <tt>Delayed</tt>:
+     * allocated array of {@code Delayed}:
      *
      * <pre> {@code Delayed[] a = q.toArray(new Delayed[0]);}</pre>
      *
-     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
-     * <tt>toArray()</tt>.
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
      *
      * @param a the array into which the elements of the queue are to
      *          be stored, if it is big enough; otherwise, a new array of the
diff --git a/luni/src/main/java/java/util/concurrent/Delayed.java b/luni/src/main/java/java/util/concurrent/Delayed.java
index 39d927c..6a9527d 100644
--- a/luni/src/main/java/java/util/concurrent/Delayed.java
+++ b/luni/src/main/java/java/util/concurrent/Delayed.java
@@ -11,8 +11,8 @@
  * acted upon after a given delay.
  *
  * <p>An implementation of this interface must define a
- * <tt>compareTo</tt> method that provides an ordering consistent with
- * its <tt>getDelay</tt> method.
+ * {@code compareTo} method that provides an ordering consistent with
+ * its {@code getDelay} method.
  *
  * @since 1.5
  * @author Doug Lea
diff --git a/luni/src/main/java/java/util/concurrent/Exchanger.java b/luni/src/main/java/java/util/concurrent/Exchanger.java
index 6069dce..01d5960 100644
--- a/luni/src/main/java/java/util/concurrent/Exchanger.java
+++ b/luni/src/main/java/java/util/concurrent/Exchanger.java
@@ -6,7 +6,8 @@
  */
 
 package java.util.concurrent;
-import java.util.concurrent.atomic.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.LockSupport;
 
 /**
@@ -73,486 +74,427 @@
  * @param <V> The type of objects that may be exchanged
  */
 public class Exchanger<V> {
+
     /*
-     * Algorithm Description:
+     * Overview: The core algorithm is, for an exchange "slot",
+     * and a participant (caller) with an item:
      *
-     * The basic idea is to maintain a "slot", which is a reference to
-     * a Node containing both an Item to offer and a "hole" waiting to
-     * get filled in.  If an incoming "occupying" thread sees that the
-     * slot is null, it CAS'es (compareAndSets) a Node there and waits
-     * for another to invoke exchange.  That second "fulfilling" thread
-     * sees that the slot is non-null, and so CASes it back to null,
-     * also exchanging items by CASing the hole, plus waking up the
-     * occupying thread if it is blocked.  In each case CAS'es may
-     * fail because a slot at first appears non-null but is null upon
-     * CAS, or vice-versa.  So threads may need to retry these
-     * actions.
+     * for (;;) {
+     *   if (slot is empty) {                       // offer
+     *     place item in a Node;
+     *     if (can CAS slot from empty to node) {
+     *       wait for release;
+     *       return matching item in node;
+     *     }
+     *   }
+     *   else if (can CAS slot from node to empty) { // release
+     *     get the item in node;
+     *     set matching item in node;
+     *     release waiting thread;
+     *   }
+     *   // else retry on CAS failure
+     * }
      *
-     * This simple approach works great when there are only a few
-     * threads using an Exchanger, but performance rapidly
-     * deteriorates due to CAS contention on the single slot when
-     * there are lots of threads using an exchanger.  So instead we use
-     * an "arena"; basically a kind of hash table with a dynamically
-     * varying number of slots, any one of which can be used by
-     * threads performing an exchange.  Incoming threads pick slots
-     * based on a hash of their Thread ids.  If an incoming thread
-     * fails to CAS in its chosen slot, it picks an alternative slot
-     * instead.  And similarly from there.  If a thread successfully
-     * CASes into a slot but no other thread arrives, it tries
-     * another, heading toward the zero slot, which always exists even
-     * if the table shrinks.  The particular mechanics controlling this
-     * are as follows:
+     * This is among the simplest forms of a "dual data structure" --
+     * see Scott and Scherer's DISC 04 paper and
+     * http://www.cs.rochester.edu/research/synchronization/pseudocode/duals.html
      *
-     * Waiting: Slot zero is special in that it is the only slot that
-     * exists when there is no contention.  A thread occupying slot
-     * zero will block if no thread fulfills it after a short spin.
-     * In other cases, occupying threads eventually give up and try
-     * another slot.  Waiting threads spin for a while (a period that
-     * should be a little less than a typical context-switch time)
-     * before either blocking (if slot zero) or giving up (if other
-     * slots) and restarting.  There is no reason for threads to block
-     * unless there are unlikely to be any other threads present.
-     * Occupants are mainly avoiding memory contention so sit there
-     * quietly polling for a shorter period than it would take to
-     * block and then unblock them.  Non-slot-zero waits that elapse
-     * because of lack of other threads waste around one extra
-     * context-switch time per try, which is still on average much
-     * faster than alternative approaches.
+     * This works great in principle. But in practice, like many
+     * algorithms centered on atomic updates to a single location, it
+     * scales horribly when there are more than a few participants
+     * using the same Exchanger. So the implementation instead uses a
+     * form of elimination arena, that spreads out this contention by
+     * arranging that some threads typically use different slots,
+     * while still ensuring that eventually, any two parties will be
+     * able to exchange items. That is, we cannot completely partition
+     * across threads, but instead give threads arena indices that
+     * will on average grow under contention and shrink under lack of
+     * contention. We approach this by defining the Nodes that we need
+     * anyway as ThreadLocals, and include in them per-thread index
+     * and related bookkeeping state. (We can safely reuse per-thread
+     * nodes rather than creating them fresh each time because slots
+     * alternate between pointing to a node vs null, so cannot
+     * encounter ABA problems. However, we do need some care in
+     * resetting them between uses.)
      *
-     * Sizing: Usually, using only a few slots suffices to reduce
-     * contention.  Especially with small numbers of threads, using
-     * too many slots can lead to just as poor performance as using
-     * too few of them, and there's not much room for error.  The
-     * variable "max" maintains the number of slots actually in
-     * use.  It is increased when a thread sees too many CAS
-     * failures.  (This is analogous to resizing a regular hash table
-     * based on a target load factor, except here, growth steps are
-     * just one-by-one rather than proportional.)  Growth requires
-     * contention failures in each of three tried slots.  Requiring
-     * multiple failures for expansion copes with the fact that some
-     * failed CASes are not due to contention but instead to simple
-     * races between two threads or thread pre-emptions occurring
-     * between reading and CASing.  Also, very transient peak
-     * contention can be much higher than the average sustainable
-     * levels.  An attempt to decrease the max limit is usually made
-     * when a non-slot-zero wait elapses without being fulfilled.
-     * Threads experiencing elapsed waits move closer to zero, so
-     * eventually find existing (or future) threads even if the table
-     * has been shrunk due to inactivity.  The chosen mechanics and
-     * thresholds for growing and shrinking are intrinsically
-     * entangled with indexing and hashing inside the exchange code,
-     * and can't be nicely abstracted out.
+     * Implementing an effective arena requires allocating a bunch of
+     * space, so we only do so upon detecting contention (except on
+     * uniprocessors, where they wouldn't help, so aren't used).
+     * Otherwise, exchanges use the single-slot slotExchange method.
+     * On contention, not only must the slots be in different
+     * locations, but the locations must not encounter memory
+     * contention due to being on the same cache line (or more
+     * generally, the same coherence unit).  Because, as of this
+     * writing, there is no way to determine cacheline size, we define
+     * a value that is enough for common platforms.  Additionally,
+     * extra care elsewhere is taken to avoid other false/unintended
+     * sharing and to enhance locality, including adding padding to
+     * Nodes, embedding "bound" as an Exchanger field, and reworking
+     * some park/unpark mechanics compared to LockSupport versions.
      *
-     * Hashing: Each thread picks its initial slot to use in accord
-     * with a simple hashcode.  The sequence is the same on each
-     * encounter by any given thread, but effectively random across
-     * threads.  Using arenas encounters the classic cost vs quality
-     * tradeoffs of all hash tables.  Here, we use a one-step FNV-1a
-     * hash code based on the current thread's Thread.getId(), along
-     * with a cheap approximation to a mod operation to select an
-     * index.  The downside of optimizing index selection in this way
-     * is that the code is hardwired to use a maximum table size of
-     * 32.  But this value more than suffices for known platforms and
-     * applications.
+     * The arena starts out with only one used slot. We expand the
+     * effective arena size by tracking collisions; i.e., failed CASes
+     * while trying to exchange. By nature of the above algorithm, the
+     * only kinds of collision that reliably indicate contention are
+     * when two attempted releases collide -- one of two attempted
+     * offers can legitimately fail to CAS without indicating
+     * contention by more than one other thread. (Note: it is possible
+     * but not worthwhile to more precisely detect contention by
+     * reading slot values after CAS failures.)  When a thread has
+     * collided at each slot within the current arena bound, it tries
+     * to expand the arena size by one. We track collisions within
+     * bounds by using a version (sequence) number on the "bound"
+     * field, and conservatively reset collision counts when a
+     * participant notices that bound has been updated (in either
+     * direction).
      *
-     * Probing: On sensed contention of a selected slot, we probe
-     * sequentially through the table, analogously to linear probing
-     * after collision in a hash table.  (We move circularly, in
-     * reverse order, to mesh best with table growth and shrinkage
-     * rules.)  Except that to minimize the effects of false-alarms
-     * and cache thrashing, we try the first selected slot twice
-     * before moving.
+     * The effective arena size is reduced (when there is more than
+     * one slot) by giving up on waiting after a while and trying to
+     * decrement the arena size on expiration. The value of "a while"
+     * is an empirical matter.  We implement by piggybacking on the
+     * use of spin->yield->block that is essential for reasonable
+     * waiting performance anyway -- in a busy exchanger, offers are
+     * usually almost immediately released, in which case context
+     * switching on multiprocessors is extremely slow/wasteful.  Arena
+     * waits just omit the blocking part, and instead cancel. The spin
+     * count is empirically chosen to be a value that avoids blocking
+     * 99% of the time under maximum sustained exchange rates on a
+     * range of test machines. Spins and yields entail some limited
+     * randomness (using a cheap xorshift) to avoid regular patterns
+     * that can induce unproductive grow/shrink cycles. (Using a
+     * pseudorandom also helps regularize spin cycle duration by
+     * making branches unpredictable.)  Also, during an offer, a
+     * waiter can "know" that it will be released when its slot has
+     * changed, but cannot yet proceed until match is set.  In the
+     * mean time it cannot cancel the offer, so instead spins/yields.
+     * Note: It is possible to avoid this secondary check by changing
+     * the linearization point to be a CAS of the match field (as done
+     * in one case in the Scott & Scherer DISC paper), which also
+     * increases asynchrony a bit, at the expense of poorer collision
+     * detection and inability to always reuse per-thread nodes. So
+     * the current scheme is typically a better tradeoff.
      *
-     * Padding: Even with contention management, slots are heavily
-     * contended, so use cache-padding to avoid poor memory
-     * performance.  Because of this, slots are lazily constructed
-     * only when used, to avoid wasting this space unnecessarily.
-     * While isolation of locations is not much of an issue at first
-     * in an application, as time goes on and garbage-collectors
-     * perform compaction, slots are very likely to be moved adjacent
-     * to each other, which can cause much thrashing of cache lines on
-     * MPs unless padding is employed.
+     * On collisions, indices traverse the arena cyclically in reverse
+     * order, restarting at the maximum index (which will tend to be
+     * sparsest) when bounds change. (On expirations, indices instead
+     * are halved until reaching 0.) It is possible (and has been
+     * tried) to use randomized, prime-value-stepped, or double-hash
+     * style traversal instead of simple cyclic traversal to reduce
+     * bunching.  But empirically, whatever benefits these may have
+     * don't overcome their added overhead: We are managing operations
+     * that occur very quickly unless there is sustained contention,
+     * so simpler/faster control policies work better than more
+     * accurate but slower ones.
      *
-     * This is an improvement of the algorithm described in the paper
-     * "A Scalable Elimination-based Exchange Channel" by William
-     * Scherer, Doug Lea, and Michael Scott in Proceedings of SCOOL05
-     * workshop.  Available at: http://hdl.handle.net/1802/2104
+     * Because we use expiration for arena size control, we cannot
+     * throw TimeoutExceptions in the timed version of the public
+     * exchange method until the arena size has shrunken to zero (or
+     * the arena isn't enabled). This may delay response to timeout
+     * but is still within spec.
+     *
+     * Essentially all of the implementation is in methods
+     * slotExchange and arenaExchange. These have similar overall
+     * structure, but differ in too many details to combine. The
+     * slotExchange method uses the single Exchanger field "slot"
+     * rather than arena array elements. However, it still needs
+     * minimal collision detection to trigger arena construction.
+     * (The messiest part is making sure interrupt status and
+     * InterruptedExceptions come out right during transitions when
+     * both methods may be called. This is done by using null return
+     * as a sentinel to recheck interrupt status.)
+     *
+     * As is too common in this sort of code, methods are monolithic
+     * because most of the logic relies on reads of fields that are
+     * maintained as local variables so can't be nicely factored --
+     * mainly, here, bulky spin->yield->block/cancel code), and
+     * heavily dependent on intrinsics (Unsafe) to use inlined
+     * embedded CAS and related memory access operations (that tend
+     * not to be as readily inlined by dynamic compilers when they are
+     * hidden behind other methods that would more nicely name and
+     * encapsulate the intended effects). This includes the use of
+     * putOrderedX to clear fields of the per-thread Nodes between
+     * uses. Note that field Node.item is not declared as volatile
+     * even though it is read by releasing threads, because they only
+     * do so after CAS operations that must precede access, and all
+     * uses by the owning thread are otherwise acceptably ordered by
+     * other operations. (Because the actual points of atomicity are
+     * slot CASes, it would also be legal for the write to Node.match
+     * in a release to be weaker than a full volatile write. However,
+     * this is not done because it could allow further postponement of
+     * the write, delaying progress.)
      */
 
+    /**
+     * The byte distance (as a shift value) between any two used slots
+     * in the arena.  1 << ASHIFT should be at least cacheline size.
+     */
+    private static final int ASHIFT = 7;
+
+    /**
+     * The maximum supported arena index. The maximum allocatable
+     * arena size is MMASK + 1. Must be a power of two minus one, less
+     * than (1<<(31-ASHIFT)). The cap of 255 (0xff) more than suffices
+     * for the expected scaling limits of the main algorithms.
+     */
+    private static final int MMASK = 0xff;
+
+    /**
+     * Unit for sequence/version bits of bound field. Each successful
+     * change to the bound also adds SEQ.
+     */
+    private static final int SEQ = MMASK + 1;
+
     /** The number of CPUs, for sizing and spin control */
     private static final int NCPU = Runtime.getRuntime().availableProcessors();
 
     /**
-     * The capacity of the arena.  Set to a value that provides more
-     * than enough space to handle contention.  On small machines
-     * most slots won't be used, but it is still not wasted because
-     * the extra space provides some machine-level address padding
-     * to minimize interference with heavily CAS'ed Slot locations.
-     * And on very large machines, performance eventually becomes
-     * bounded by memory bandwidth, not numbers of threads/CPUs.
-     * This constant cannot be changed without also modifying
-     * indexing and hashing algorithms.
+     * The maximum slot index of the arena: The number of slots that
+     * can in principle hold all threads without contention, or at
+     * most the maximum indexable value.
      */
-    private static final int CAPACITY = 32;
+    static final int FULL = (NCPU >= (MMASK << 1)) ? MMASK : NCPU >>> 1;
 
     /**
-     * The value of "max" that will hold all threads without
-     * contention.  When this value is less than CAPACITY, some
-     * otherwise wasted expansion can be avoided.
+     * The bound for spins while waiting for a match. The actual
+     * number of iterations will on average be about twice this value
+     * due to randomization. Note: Spinning is disabled when NCPU==1.
      */
-    private static final int FULL =
-        Math.max(0, Math.min(CAPACITY, NCPU / 2) - 1);
-
-    /**
-     * The number of times to spin (doing nothing except polling a
-     * memory location) before blocking or giving up while waiting to
-     * be fulfilled.  Should be zero on uniprocessors.  On
-     * multiprocessors, this value should be large enough so that two
-     * threads exchanging items as fast as possible block only when
-     * one of them is stalled (due to GC or preemption), but not much
-     * longer, to avoid wasting CPU resources.  Seen differently, this
-     * value is a little over half the number of cycles of an average
-     * context switch time on most systems.  The value here is
-     * approximately the average of those across a range of tested
-     * systems.
-     */
-    private static final int SPINS = (NCPU == 1) ? 0 : 2000;
-
-    /**
-     * The number of times to spin before blocking in timed waits.
-     * Timed waits spin more slowly because checking the time takes
-     * time.  The best value relies mainly on the relative rate of
-     * System.nanoTime vs memory accesses.  The value is empirically
-     * derived to work well across a variety of systems.
-     */
-    private static final int TIMED_SPINS = SPINS / 20;
-
-    /**
-     * Sentinel item representing cancellation of a wait due to
-     * interruption, timeout, or elapsed spin-waits.  This value is
-     * placed in holes on cancellation, and used as a return value
-     * from waiting methods to indicate failure to set or get hole.
-     */
-    private static final Object CANCEL = new Object();
+    private static final int SPINS = 1 << 10;
 
     /**
      * Value representing null arguments/returns from public
-     * methods.  This disambiguates from internal requirement that
-     * holes start out as null to mean they are not yet set.
+     * methods. Needed because the API originally didn't disallow null
+     * arguments, which it should have.
      */
     private static final Object NULL_ITEM = new Object();
 
     /**
-     * Nodes hold partially exchanged data.  This class
-     * opportunistically subclasses AtomicReference to represent the
-     * hole.  So get() returns hole, and compareAndSet CAS'es value
-     * into hole.  This class cannot be parameterized as "V" because
-     * of the use of non-V CANCEL sentinels.
+     * Sentinel value returned by internal exchange methods upon
+     * timeout, to avoid need for separate timed versions of these
+     * methods.
      */
-    private static final class Node extends AtomicReference<Object> {
-        /** The element offered by the Thread creating this node. */
-        public final Object item;
+    private static final Object TIMED_OUT = new Object();
 
-        /** The Thread waiting to be signalled; null until waiting. */
-        public volatile Thread waiter;
+    /**
+     * Nodes hold partially exchanged data, plus other per-thread
+     * bookkeeping.
+     */
+    static final class Node {
+        int index;              // Arena index
+        int bound;              // Last recorded value of Exchanger.bound
+        int collides;           // Number of CAS failures at current bound
+        int hash;               // Pseudo-random for spins
+        Object item;            // This thread's current item
+        volatile Object match;  // Item provided by releasing thread
+        volatile Thread parked; // Set to this thread when parked, else null
 
-        /**
-         * Creates node with given item and empty hole.
-         * @param item the item
-         */
-        public Node(Object item) {
-            this.item = item;
-        }
+        // Padding to ameliorate unfortunate memory placements
+        Object p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pa, pb, pc, pd, pe, pf;
+        Object q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, qa, qb, qc, qd, qe, qf;
+    }
+
+    /** The corresponding thread local class */
+    static final class Participant extends ThreadLocal<Node> {
+        public Node initialValue() { return new Node(); }
     }
 
     /**
-     * A Slot is an AtomicReference with heuristic padding to lessen
-     * cache effects of this heavily CAS'ed location.  While the
-     * padding adds noticeable space, all slots are created only on
-     * demand, and there will be more than one of them only when it
-     * would improve throughput more than enough to outweigh using
-     * extra space.
+     * Per-thread state
      */
-    private static final class Slot extends AtomicReference<Object> {
-        // Improve likelihood of isolation on <= 128 byte cache lines.
-        // We used to target 64 byte cache lines, but some x86s (including
-        // i7 under some BIOSes) actually use 128 byte cache lines.
-        long q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, qa, qb, qc, qd, qe;
-    }
+    private final Participant participant;
 
     /**
-     * Slot array.  Elements are lazily initialized when needed.
-     * Declared volatile to enable double-checked lazy construction.
+     * Elimination array; null until enabled (within slotExchange).
+     * Element accesses use emulation of volatile gets and CAS.
      */
-    private volatile Slot[] arena = new Slot[CAPACITY];
+    private volatile Node[] arena;
 
     /**
-     * The maximum slot index being used.  The value sometimes
-     * increases when a thread experiences too many CAS contentions,
-     * and sometimes decreases when a spin-wait elapses.  Changes
-     * are performed only via compareAndSet, to avoid stale values
-     * when a thread happens to stall right before setting.
+     * Slot used until contention detected.
      */
-    private final AtomicInteger max = new AtomicInteger();
+    private volatile Node slot;
 
     /**
-     * Main exchange function, handling the different policy variants.
-     * Uses Object, not "V" as argument and return value to simplify
-     * handling of sentinel values.  Callers from public methods decode
-     * and cast accordingly.
+     * The index of the largest valid arena position, OR'ed with SEQ
+     * number in high bits, incremented on each update.  The initial
+     * update from 0 to SEQ is used to ensure that the arena array is
+     * constructed only once.
+     */
+    private volatile int bound;
+
+    /**
+     * Exchange function when arenas enabled. See above for explanation.
      *
      * @param item the (non-null) item to exchange
      * @param timed true if the wait is timed
-     * @param nanos if timed, the maximum wait time
-     * @return the other thread's item, or CANCEL if interrupted or timed out
+     * @param ns if timed, the maximum wait time, else 0L
+     * @return the other thread's item; or null if interrupted; or
+     * TIMED_OUT if timed and timed out
      */
-    private Object doExchange(Object item, boolean timed, long nanos) {
-        Node me = new Node(item);                 // Create in case occupying
-        int index = hashIndex();                  // Index of current slot
-        int fails = 0;                            // Number of CAS failures
-
-        for (;;) {
-            Object y;                             // Contents of current slot
-            Slot slot = arena[index];
-            if (slot == null)                     // Lazily initialize slots
-                createSlot(index);                // Continue loop to reread
-            else if ((y = slot.get()) != null &&  // Try to fulfill
-                     slot.compareAndSet(y, null)) {
-                Node you = (Node)y;               // Transfer item
-                if (you.compareAndSet(null, item)) {
-                    LockSupport.unpark(you.waiter);
-                    return you.item;
-                }                                 // Else cancelled; continue
-            }
-            else if (y == null &&                 // Try to occupy
-                     slot.compareAndSet(null, me)) {
-                if (index == 0)                   // Blocking wait for slot 0
-                    return timed ?
-                        awaitNanos(me, slot, nanos) :
-                        await(me, slot);
-                Object v = spinWait(me, slot);    // Spin wait for non-0
-                if (v != CANCEL)
-                    return v;
-                me = new Node(item);              // Throw away cancelled node
-                int m = max.get();
-                if (m > (index >>>= 1))           // Decrease index
-                    max.compareAndSet(m, m - 1);  // Maybe shrink table
-            }
-            else if (++fails > 1) {               // Allow 2 fails on 1st slot
-                int m = max.get();
-                if (fails > 3 && m < FULL && max.compareAndSet(m, m + 1))
-                    index = m + 1;                // Grow on 3rd failed slot
-                else if (--index < 0)
-                    index = m;                    // Circularly traverse
-            }
-        }
-    }
-
-    /**
-     * Returns a hash index for the current thread.  Uses a one-step
-     * FNV-1a hash code (http://www.isthe.com/chongo/tech/comp/fnv/)
-     * based on the current thread's Thread.getId().  These hash codes
-     * have more uniform distribution properties with respect to small
-     * moduli (here 1-31) than do other simple hashing functions.
-     *
-     * <p>To return an index between 0 and max, we use a cheap
-     * approximation to a mod operation, that also corrects for bias
-     * due to non-power-of-2 remaindering (see {@link
-     * java.util.Random#nextInt}).  Bits of the hashcode are masked
-     * with "nbits", the ceiling power of two of table size (looked up
-     * in a table packed into three ints).  If too large, this is
-     * retried after rotating the hash by nbits bits, while forcing new
-     * top bit to 0, which guarantees eventual termination (although
-     * with a non-random-bias).  This requires an average of less than
-     * 2 tries for all table sizes, and has a maximum 2% difference
-     * from perfectly uniform slot probabilities when applied to all
-     * possible hash codes for sizes less than 32.
-     *
-     * @return a per-thread-random index, 0 <= index < max
-     */
-    private final int hashIndex() {
-        long id = Thread.currentThread().getId();
-        int hash = (((int)(id ^ (id >>> 32))) ^ 0x811c9dc5) * 0x01000193;
-
-        int m = max.get();
-        int nbits = (((0xfffffc00  >> m) & 4) | // Compute ceil(log2(m+1))
-                     ((0x000001f8 >>> m) & 2) | // The constants hold
-                     ((0xffff00f2 >>> m) & 1)); // a lookup table
-        int index;
-        while ((index = hash & ((1 << nbits) - 1)) > m)       // May retry on
-            hash = (hash >>> nbits) | (hash << (33 - nbits)); // non-power-2 m
-        return index;
-    }
-
-    /**
-     * Creates a new slot at given index.  Called only when the slot
-     * appears to be null.  Relies on double-check using builtin
-     * locks, since they rarely contend.  This in turn relies on the
-     * arena array being declared volatile.
-     *
-     * @param index the index to add slot at
-     */
-    private void createSlot(int index) {
-        // Create slot outside of lock to narrow sync region
-        Slot newSlot = new Slot();
-        Slot[] a = arena;
-        synchronized (a) {
-            if (a[index] == null)
-                a[index] = newSlot;
-        }
-    }
-
-    /**
-     * Tries to cancel a wait for the given node waiting in the given
-     * slot, if so, helping clear the node from its slot to avoid
-     * garbage retention.
-     *
-     * @param node the waiting node
-     * @param slot the slot it is waiting in
-     * @return true if successfully cancelled
-     */
-    private static boolean tryCancel(Node node, Slot slot) {
-        if (!node.compareAndSet(null, CANCEL))
-            return false;
-        if (slot.get() == node) // pre-check to minimize contention
-            slot.compareAndSet(node, null);
-        return true;
-    }
-
-    // Three forms of waiting. Each just different enough not to merge
-    // code with others.
-
-    /**
-     * Spin-waits for hole for a non-0 slot.  Fails if spin elapses
-     * before hole filled.  Does not check interrupt, relying on check
-     * in public exchange method to abort if interrupted on entry.
-     *
-     * @param node the waiting node
-     * @return on success, the hole; on failure, CANCEL
-     */
-    private static Object spinWait(Node node, Slot slot) {
-        int spins = SPINS;
-        for (;;) {
-            Object v = node.get();
-            if (v != null)
+    private final Object arenaExchange(Object item, boolean timed, long ns) {
+        Node[] a = arena;
+        Node p = participant.get();
+        for (int i = p.index;;) {                      // access slot at i
+            int b, m, c; long j;                       // j is raw array offset
+            Node q = (Node)U.getObjectVolatile(a, j = (i << ASHIFT) + ABASE);
+            if (q != null && U.compareAndSwapObject(a, j, q, null)) {
+                Object v = q.item;                     // release
+                q.match = item;
+                Thread w = q.parked;
+                if (w != null)
+                    U.unpark(w);
                 return v;
-            else if (spins > 0)
-                --spins;
-            else
-                tryCancel(node, slot);
-        }
-    }
-
-    /**
-     * Waits for (by spinning and/or blocking) and gets the hole
-     * filled in by another thread.  Fails if interrupted before
-     * hole filled.
-     *
-     * When a node/thread is about to block, it sets its waiter field
-     * and then rechecks state at least one more time before actually
-     * parking, thus covering race vs fulfiller noticing that waiter
-     * is non-null so should be woken.
-     *
-     * Thread interruption status is checked only surrounding calls to
-     * park.  The caller is assumed to have checked interrupt status
-     * on entry.
-     *
-     * @param node the waiting node
-     * @return on success, the hole; on failure, CANCEL
-     */
-    private static Object await(Node node, Slot slot) {
-        Thread w = Thread.currentThread();
-        int spins = SPINS;
-        for (;;) {
-            Object v = node.get();
-            if (v != null)
-                return v;
-            else if (spins > 0)                 // Spin-wait phase
-                --spins;
-            else if (node.waiter == null)       // Set up to block next
-                node.waiter = w;
-            else if (w.isInterrupted())         // Abort on interrupt
-                tryCancel(node, slot);
-            else                                // Block
-                LockSupport.park(node);
-        }
-    }
-
-    /**
-     * Waits for (at index 0) and gets the hole filled in by another
-     * thread.  Fails if timed out or interrupted before hole filled.
-     * Same basic logic as untimed version, but a bit messier.
-     *
-     * @param node the waiting node
-     * @param nanos the wait time
-     * @return on success, the hole; on failure, CANCEL
-     */
-    private Object awaitNanos(Node node, Slot slot, long nanos) {
-        int spins = TIMED_SPINS;
-        long lastTime = 0;
-        Thread w = null;
-        for (;;) {
-            Object v = node.get();
-            if (v != null)
-                return v;
-            long now = System.nanoTime();
-            if (w == null)
-                w = Thread.currentThread();
-            else
-                nanos -= now - lastTime;
-            lastTime = now;
-            if (nanos > 0) {
-                if (spins > 0)
-                    --spins;
-                else if (node.waiter == null)
-                    node.waiter = w;
-                else if (w.isInterrupted())
-                    tryCancel(node, slot);
-                else
-                    LockSupport.parkNanos(node, nanos);
             }
-            else if (tryCancel(node, slot) && !w.isInterrupted())
-                return scanOnTimeout(node);
-        }
-    }
-
-    /**
-     * Sweeps through arena checking for any waiting threads.  Called
-     * only upon return from timeout while waiting in slot 0.  When a
-     * thread gives up on a timed wait, it is possible that a
-     * previously-entered thread is still waiting in some other
-     * slot.  So we scan to check for any.  This is almost always
-     * overkill, but decreases the likelihood of timeouts when there
-     * are other threads present to far less than that in lock-based
-     * exchangers in which earlier-arriving threads may still be
-     * waiting on entry locks.
-     *
-     * @param node the waiting node
-     * @return another thread's item, or CANCEL
-     */
-    private Object scanOnTimeout(Node node) {
-        Object y;
-        for (int j = arena.length - 1; j >= 0; --j) {
-            Slot slot = arena[j];
-            if (slot != null) {
-                while ((y = slot.get()) != null) {
-                    if (slot.compareAndSet(y, null)) {
-                        Node you = (Node)y;
-                        if (you.compareAndSet(null, node.item)) {
-                            LockSupport.unpark(you.waiter);
-                            return you.item;
+            else if (i <= (m = (b = bound) & MMASK) && q == null) {
+                p.item = item;                         // offer
+                if (U.compareAndSwapObject(a, j, null, p)) {
+                    long end = (timed && m == 0) ? System.nanoTime() + ns : 0L;
+                    Thread t = Thread.currentThread(); // wait
+                    for (int h = p.hash, spins = SPINS;;) {
+                        Object v = p.match;
+                        if (v != null) {
+                            U.putOrderedObject(p, MATCH, null);
+                            p.item = null;             // clear for next use
+                            p.hash = h;
+                            return v;
+                        }
+                        else if (spins > 0) {
+                            h ^= h << 1; h ^= h >>> 3; h ^= h << 10; // xorshift
+                            if (h == 0)                // initialize hash
+                                h = SPINS | (int)t.getId();
+                            else if (h < 0 &&          // approx 50% true
+                                     (--spins & ((SPINS >>> 1) - 1)) == 0)
+                                Thread.yield();        // two yields per wait
+                        }
+                        else if (U.getObjectVolatile(a, j) != p)
+                            spins = SPINS;       // releaser hasn't set match yet
+                        else if (!t.isInterrupted() && m == 0 &&
+                                 (!timed ||
+                                  (ns = end - System.nanoTime()) > 0L)) {
+                            U.putObject(t, BLOCKER, this); // emulate LockSupport
+                            p.parked = t;              // minimize window
+                            if (U.getObjectVolatile(a, j) == p)
+                                U.park(false, ns);
+                            p.parked = null;
+                            U.putObject(t, BLOCKER, null);
+                        }
+                        else if (U.getObjectVolatile(a, j) == p &&
+                                 U.compareAndSwapObject(a, j, p, null)) {
+                            if (m != 0)                // try to shrink
+                                U.compareAndSwapInt(this, BOUND, b, b + SEQ - 1);
+                            p.item = null;
+                            p.hash = h;
+                            i = p.index >>>= 1;        // descend
+                            if (Thread.interrupted())
+                                return null;
+                            if (timed && m == 0 && ns <= 0L)
+                                return TIMED_OUT;
+                            break;                     // expired; restart
                         }
                     }
                 }
+                else
+                    p.item = null;                     // clear offer
+            }
+            else {
+                if (p.bound != b) {                    // stale; reset
+                    p.bound = b;
+                    p.collides = 0;
+                    i = (i != m || m == 0) ? m : m - 1;
+                }
+                else if ((c = p.collides) < m || m == FULL ||
+                         !U.compareAndSwapInt(this, BOUND, b, b + SEQ + 1)) {
+                    p.collides = c + 1;
+                    i = (i == 0) ? m : i - 1;          // cyclically traverse
+                }
+                else
+                    i = m + 1;                         // grow
+                p.index = i;
             }
         }
-        return CANCEL;
+    }
+
+    /**
+     * Exchange function used until arenas enabled. See above for explanation.
+     *
+     * @param item the item to exchange
+     * @param timed true if the wait is timed
+     * @param ns if timed, the maximum wait time, else 0L
+     * @return the other thread's item; or null if either the arena
+     * was enabled or the thread was interrupted before completion; or
+     * TIMED_OUT if timed and timed out
+     */
+    private final Object slotExchange(Object item, boolean timed, long ns) {
+        Node p = participant.get();
+        Thread t = Thread.currentThread();
+        if (t.isInterrupted()) // preserve interrupt status so caller can recheck
+            return null;
+
+        for (Node q;;) {
+            if ((q = slot) != null) {
+                if (U.compareAndSwapObject(this, SLOT, q, null)) {
+                    Object v = q.item;
+                    q.match = item;
+                    Thread w = q.parked;
+                    if (w != null)
+                        U.unpark(w);
+                    return v;
+                }
+                // create arena on contention, but continue until slot null
+                if (NCPU > 1 && bound == 0 &&
+                    U.compareAndSwapInt(this, BOUND, 0, SEQ))
+                    arena = new Node[(FULL + 2) << ASHIFT];
+            }
+            else if (arena != null)
+                return null; // caller must reroute to arenaExchange
+            else {
+                p.item = item;
+                if (U.compareAndSwapObject(this, SLOT, null, p))
+                    break;
+                p.item = null;
+            }
+        }
+
+        // await release
+        int h = p.hash;
+        long end = timed ? System.nanoTime() + ns : 0L;
+        int spins = (NCPU > 1) ? SPINS : 1;
+        Object v;
+        while ((v = p.match) == null) {
+            if (spins > 0) {
+                h ^= h << 1; h ^= h >>> 3; h ^= h << 10;
+                if (h == 0)
+                    h = SPINS | (int)t.getId();
+                else if (h < 0 && (--spins & ((SPINS >>> 1) - 1)) == 0)
+                    Thread.yield();
+            }
+            else if (slot != p)
+                spins = SPINS;
+            else if (!t.isInterrupted() && arena == null &&
+                     (!timed || (ns = end - System.nanoTime()) > 0L)) {
+                U.putObject(t, BLOCKER, this);
+                p.parked = t;
+                if (slot == p)
+                    U.park(false, ns);
+                p.parked = null;
+                U.putObject(t, BLOCKER, null);
+            }
+            else if (U.compareAndSwapObject(this, SLOT, p, null)) {
+                v = timed && ns <= 0L && !t.isInterrupted() ? TIMED_OUT : null;
+                break;
+            }
+        }
+        U.putOrderedObject(p, MATCH, null);
+        p.item = null;
+        p.hash = h;
+        return v;
     }
 
     /**
      * Creates a new Exchanger.
      */
     public Exchanger() {
+        participant = new Participant();
     }
 
     /**
@@ -588,16 +530,16 @@
      * @throws InterruptedException if the current thread was
      *         interrupted while waiting
      */
+    @SuppressWarnings("unchecked")
     public V exchange(V x) throws InterruptedException {
-        if (!Thread.interrupted()) {
-            Object v = doExchange((x == null) ? NULL_ITEM : x, false, 0);
-            if (v == NULL_ITEM)
-                return null;
-            if (v != CANCEL)
-                return (V)v;
-            Thread.interrupted(); // Clear interrupt status on IE throw
-        }
-        throw new InterruptedException();
+        Object v;
+        Object item = (x == null) ? NULL_ITEM : x; // translate null args
+        if ((arena != null ||
+             (v = slotExchange(item, false, 0L)) == null) &&
+            ((Thread.interrupted() || // disambiguates null return
+              (v = arenaExchange(item, false, 0L)) == null)))
+            throw new InterruptedException();
+        return (v == NULL_ITEM) ? null : (V)v;
     }
 
     /**
@@ -635,25 +577,61 @@
      *
      * @param x the object to exchange
      * @param timeout the maximum time to wait
-     * @param unit the time unit of the <tt>timeout</tt> argument
+     * @param unit the time unit of the {@code timeout} argument
      * @return the object provided by the other thread
      * @throws InterruptedException if the current thread was
      *         interrupted while waiting
      * @throws TimeoutException if the specified waiting time elapses
      *         before another thread enters the exchange
      */
+    @SuppressWarnings("unchecked")
     public V exchange(V x, long timeout, TimeUnit unit)
         throws InterruptedException, TimeoutException {
-        if (!Thread.interrupted()) {
-            Object v = doExchange((x == null) ? NULL_ITEM : x,
-                                  true, unit.toNanos(timeout));
-            if (v == NULL_ITEM)
-                return null;
-            if (v != CANCEL)
-                return (V)v;
-            if (!Thread.interrupted())
-                throw new TimeoutException();
-        }
-        throw new InterruptedException();
+        Object v;
+        Object item = (x == null) ? NULL_ITEM : x;
+        long ns = unit.toNanos(timeout);
+        if ((arena != null ||
+             (v = slotExchange(item, true, ns)) == null) &&
+            ((Thread.interrupted() ||
+              (v = arenaExchange(item, true, ns)) == null)))
+            throw new InterruptedException();
+        if (v == TIMED_OUT)
+            throw new TimeoutException();
+        return (v == NULL_ITEM) ? null : (V)v;
     }
+
+    // Unsafe mechanics
+    private static final sun.misc.Unsafe U;
+    private static final long BOUND;
+    private static final long SLOT;
+    private static final long MATCH;
+    private static final long BLOCKER;
+    private static final int ABASE;
+    static {
+        int s;
+        try {
+            U = sun.misc.Unsafe.getUnsafe();
+            Class<?> ek = Exchanger.class;
+            Class<?> nk = Node.class;
+            Class<?> ak = Node[].class;
+            Class<?> tk = Thread.class;
+            BOUND = U.objectFieldOffset
+                (ek.getDeclaredField("bound"));
+            SLOT = U.objectFieldOffset
+                (ek.getDeclaredField("slot"));
+            MATCH = U.objectFieldOffset
+                (nk.getDeclaredField("match"));
+            BLOCKER = U.objectFieldOffset
+                (tk.getDeclaredField("parkBlocker"));
+            s = U.arrayIndexScale(ak);
+            // ABASE absorbs padding in front of element 0
+            ABASE = U.arrayBaseOffset(ak) + (1 << ASHIFT);
+
+        } catch (Exception e) {
+            throw new Error(e);
+        }
+        if ((s & (s-1)) != 0 || s > (1 << ASHIFT))
+            throw new Error("Unsupported array scale");
+    }
+
 }
diff --git a/luni/src/main/java/java/util/concurrent/ExecutionException.java b/luni/src/main/java/java/util/concurrent/ExecutionException.java
index 9bb8dee..dbfbe65 100644
--- a/luni/src/main/java/java/util/concurrent/ExecutionException.java
+++ b/luni/src/main/java/java/util/concurrent/ExecutionException.java
@@ -19,14 +19,14 @@
     private static final long serialVersionUID = 7830266012832686185L;
 
     /**
-     * Constructs an <tt>ExecutionException</tt> with no detail message.
+     * Constructs an {@code ExecutionException} with no detail message.
      * The cause is not initialized, and may subsequently be
      * initialized by a call to {@link #initCause(Throwable) initCause}.
      */
     protected ExecutionException() { }
 
     /**
-     * Constructs an <tt>ExecutionException</tt> with the specified detail
+     * Constructs an {@code ExecutionException} with the specified detail
      * message. The cause is not initialized, and may subsequently be
      * initialized by a call to {@link #initCause(Throwable) initCause}.
      *
@@ -37,7 +37,7 @@
     }
 
     /**
-     * Constructs an <tt>ExecutionException</tt> with the specified detail
+     * Constructs an {@code ExecutionException} with the specified detail
      * message and cause.
      *
      * @param  message the detail message
@@ -49,10 +49,10 @@
     }
 
     /**
-     * Constructs an <tt>ExecutionException</tt> with the specified cause.
+     * Constructs an {@code ExecutionException} with the specified cause.
      * The detail message is set to {@code (cause == null ? null :
      * cause.toString())} (which typically contains the class and
-     * detail message of <tt>cause</tt>).
+     * detail message of {@code cause}).
      *
      * @param  cause the cause (which is saved for later retrieval by the
      *         {@link #getCause()} method)
diff --git a/luni/src/main/java/java/util/concurrent/Executor.java b/luni/src/main/java/java/util/concurrent/Executor.java
index 831bf46..f55209a 100644
--- a/luni/src/main/java/java/util/concurrent/Executor.java
+++ b/luni/src/main/java/java/util/concurrent/Executor.java
@@ -10,9 +10,9 @@
  * An object that executes submitted {@link Runnable} tasks. This
  * interface provides a way of decoupling task submission from the
  * mechanics of how each task will be run, including details of thread
- * use, scheduling, etc.  An <tt>Executor</tt> is normally used
+ * use, scheduling, etc.  An {@code Executor} is normally used
  * instead of explicitly creating threads. For example, rather than
- * invoking <tt>new Thread(new(RunnableTask())).start()</tt> for each
+ * invoking {@code new Thread(new(RunnableTask())).start()} for each
  * of a set of tasks, you might use:
  *
  * <pre>
@@ -22,7 +22,7 @@
  * ...
  * </pre>
  *
- * However, the <tt>Executor</tt> interface does not strictly
+ * However, the {@code Executor} interface does not strictly
  * require that execution be asynchronous. In the simplest case, an
  * executor can run the submitted task immediately in the caller's
  * thread:
@@ -45,7 +45,7 @@
  *   }
  * }}</pre>
  *
- * Many <tt>Executor</tt> implementations impose some sort of
+ * Many {@code Executor} implementations impose some sort of
  * limitation on how and when tasks are scheduled.  The executor below
  * serializes the submission of tasks to a second executor,
  * illustrating a composite executor.
@@ -82,7 +82,7 @@
  *   }
  * }}</pre>
  *
- * The <tt>Executor</tt> implementations provided in this package
+ * The {@code Executor} implementations provided in this package
  * implement {@link ExecutorService}, which is a more extensive
  * interface.  The {@link ThreadPoolExecutor} class provides an
  * extensible thread pool implementation. The {@link Executors} class
@@ -101,11 +101,11 @@
     /**
      * Executes the given command at some time in the future.  The command
      * may execute in a new thread, in a pooled thread, or in the calling
-     * thread, at the discretion of the <tt>Executor</tt> implementation.
+     * thread, at the discretion of the {@code Executor} implementation.
      *
      * @param command the runnable task
      * @throws RejectedExecutionException if this task cannot be
-     * accepted for execution.
+     * accepted for execution
      * @throws NullPointerException if command is null
      */
     void execute(Runnable command);
diff --git a/luni/src/main/java/java/util/concurrent/ExecutorService.java b/luni/src/main/java/java/util/concurrent/ExecutorService.java
index a33ceec..4599f59 100644
--- a/luni/src/main/java/java/util/concurrent/ExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/ExecutorService.java
@@ -17,21 +17,21 @@
  * methods that can produce a {@link Future} for tracking progress of
  * one or more asynchronous tasks.
  *
- * <p> An <tt>ExecutorService</tt> can be shut down, which will cause
+ * <p>An {@code ExecutorService} can be shut down, which will cause
  * it to reject new tasks.  Two different methods are provided for
- * shutting down an <tt>ExecutorService</tt>. The {@link #shutdown}
+ * shutting down an {@code ExecutorService}. The {@link #shutdown}
  * method will allow previously submitted tasks to execute before
  * terminating, while the {@link #shutdownNow} method prevents waiting
  * tasks from starting and attempts to stop currently executing tasks.
  * Upon termination, an executor has no tasks actively executing, no
  * tasks awaiting execution, and no new tasks can be submitted.  An
- * unused <tt>ExecutorService</tt> should be shut down to allow
+ * unused {@code ExecutorService} should be shut down to allow
  * reclamation of its resources.
  *
- * <p> Method <tt>submit</tt> extends base method {@link
+ * <p>Method {@code submit} extends base method {@link
  * Executor#execute} by creating and returning a {@link Future} that
  * can be used to cancel execution and/or wait for completion.
- * Methods <tt>invokeAny</tt> and <tt>invokeAll</tt> perform the most
+ * Methods {@code invokeAny} and {@code invokeAll} perform the most
  * commonly useful forms of bulk execution, executing a collection of
  * tasks and then waiting for at least one, or all, to
  * complete. (Class {@link ExecutorCompletionService} can be used to
@@ -76,9 +76,9 @@
  *   }
  * }}</pre>
  *
- * The following method shuts down an <tt>ExecutorService</tt> in two phases,
- * first by calling <tt>shutdown</tt> to reject incoming tasks, and then
- * calling <tt>shutdownNow</tt>, if necessary, to cancel any lingering tasks:
+ * The following method shuts down an {@code ExecutorService} in two phases,
+ * first by calling {@code shutdown} to reject incoming tasks, and then
+ * calling {@code shutdownNow}, if necessary, to cancel any lingering tasks:
  *
  *  <pre> {@code
  * void shutdownAndAwaitTermination(ExecutorService pool) {
@@ -141,18 +141,18 @@
     List<Runnable> shutdownNow();
 
     /**
-     * Returns <tt>true</tt> if this executor has been shut down.
+     * Returns {@code true} if this executor has been shut down.
      *
-     * @return <tt>true</tt> if this executor has been shut down
+     * @return {@code true} if this executor has been shut down
      */
     boolean isShutdown();
 
     /**
-     * Returns <tt>true</tt> if all tasks have completed following shut down.
-     * Note that <tt>isTerminated</tt> is never <tt>true</tt> unless
-     * either <tt>shutdown</tt> or <tt>shutdownNow</tt> was called first.
+     * Returns {@code true} if all tasks have completed following shut down.
+     * Note that {@code isTerminated} is never {@code true} unless
+     * either {@code shutdown} or {@code shutdownNow} was called first.
      *
-     * @return <tt>true</tt> if all tasks have completed following shut down
+     * @return {@code true} if all tasks have completed following shut down
      */
     boolean isTerminated();
 
@@ -163,26 +163,25 @@
      *
      * @param timeout the maximum time to wait
      * @param unit the time unit of the timeout argument
-     * @return <tt>true</tt> if this executor terminated and
-     *         <tt>false</tt> if the timeout elapsed before termination
+     * @return {@code true} if this executor terminated and
+     *         {@code false} if the timeout elapsed before termination
      * @throws InterruptedException if interrupted while waiting
      */
     boolean awaitTermination(long timeout, TimeUnit unit)
         throws InterruptedException;
 
-
     /**
      * Submits a value-returning task for execution and returns a
      * Future representing the pending results of the task. The
-     * Future's <tt>get</tt> method will return the task's result upon
+     * Future's {@code get} method will return the task's result upon
      * successful completion.
      *
      * <p>
      * If you would like to immediately block waiting
      * for a task, you can use constructions of the form
-     * <tt>result = exec.submit(aCallable).get();</tt>
+     * {@code result = exec.submit(aCallable).get();}
      *
-     * <p> Note: The {@link Executors} class includes a set of methods
+     * <p>Note: The {@link Executors} class includes a set of methods
      * that can convert some other common closure-like objects,
      * for example, {@link java.security.PrivilegedAction} to
      * {@link Callable} form so they can be submitted.
@@ -197,7 +196,7 @@
 
     /**
      * Submits a Runnable task for execution and returns a Future
-     * representing that task. The Future's <tt>get</tt> method will
+     * representing that task. The Future's {@code get} method will
      * return the given result upon successful completion.
      *
      * @param task the task to submit
@@ -211,8 +210,8 @@
 
     /**
      * Submits a Runnable task for execution and returns a Future
-     * representing that task. The Future's <tt>get</tt> method will
-     * return <tt>null</tt> upon <em>successful</em> completion.
+     * representing that task. The Future's {@code get} method will
+     * return {@code null} upon <em>successful</em> completion.
      *
      * @param task the task to submit
      * @return a Future representing pending completion of the task
@@ -225,7 +224,7 @@
     /**
      * Executes the given tasks, returning a list of Futures holding
      * their status and results when all complete.
-     * {@link Future#isDone} is <tt>true</tt> for each
+     * {@link Future#isDone} is {@code true} for each
      * element of the returned list.
      * Note that a <em>completed</em> task could have
      * terminated either normally or by throwing an exception.
@@ -233,16 +232,15 @@
      * collection is modified while this operation is in progress.
      *
      * @param tasks the collection of tasks
-     * @return A list of Futures representing the tasks, in the same
+     * @return a list of Futures representing the tasks, in the same
      *         sequential order as produced by the iterator for the
-     *         given task list, each of which has completed.
+     *         given task list, each of which has completed
      * @throws InterruptedException if interrupted while waiting, in
-     *         which case unfinished tasks are cancelled.
-     * @throws NullPointerException if tasks or any of its elements are <tt>null</tt>
+     *         which case unfinished tasks are cancelled
+     * @throws NullPointerException if tasks or any of its elements are {@code null}
      * @throws RejectedExecutionException if any task cannot be
      *         scheduled for execution
      */
-
     <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
         throws InterruptedException;
 
@@ -250,7 +248,7 @@
      * Executes the given tasks, returning a list of Futures holding
      * their status and results
      * when all complete or the timeout expires, whichever happens first.
-     * {@link Future#isDone} is <tt>true</tt> for each
+     * {@link Future#isDone} is {@code true} for each
      * element of the returned list.
      * Upon return, tasks that have not completed are cancelled.
      * Note that a <em>completed</em> task could have
@@ -269,7 +267,7 @@
      * @throws InterruptedException if interrupted while waiting, in
      *         which case unfinished tasks are cancelled
      * @throws NullPointerException if tasks, any of its elements, or
-     *         unit are <tt>null</tt>
+     *         unit are {@code null}
      * @throws RejectedExecutionException if any task cannot be scheduled
      *         for execution
      */
@@ -289,7 +287,7 @@
      * @return the result returned by one of the tasks
      * @throws InterruptedException if interrupted while waiting
      * @throws NullPointerException if tasks or any element task
-     *         subject to execution is <tt>null</tt>
+     *         subject to execution is {@code null}
      * @throws IllegalArgumentException if tasks is empty
      * @throws ExecutionException if no task successfully completes
      * @throws RejectedExecutionException if tasks cannot be scheduled
@@ -310,10 +308,10 @@
      * @param tasks the collection of tasks
      * @param timeout the maximum time to wait
      * @param unit the time unit of the timeout argument
-     * @return the result returned by one of the tasks.
+     * @return the result returned by one of the tasks
      * @throws InterruptedException if interrupted while waiting
      * @throws NullPointerException if tasks, or unit, or any element
-     *         task subject to execution is <tt>null</tt>
+     *         task subject to execution is {@code null}
      * @throws TimeoutException if the given timeout elapses before
      *         any task successfully completes
      * @throws ExecutionException if no task successfully completes
diff --git a/luni/src/main/java/java/util/concurrent/Executors.java b/luni/src/main/java/java/util/concurrent/Executors.java
index b4f03ba..53c68fc 100644
--- a/luni/src/main/java/java/util/concurrent/Executors.java
+++ b/luni/src/main/java/java/util/concurrent/Executors.java
@@ -34,7 +34,7 @@
  *        that sets newly created threads to a known state.
  *   <li> Methods that create and return a {@link Callable}
  *        out of other closure-like forms, so they can be used
- *        in execution methods requiring <tt>Callable</tt>.
+ *        in execution methods requiring {@code Callable}.
  * </ul>
  *
  * @since 1.5
@@ -45,7 +45,7 @@
     /**
      * Creates a thread pool that reuses a fixed number of threads
      * operating off a shared unbounded queue.  At any point, at most
-     * <tt>nThreads</tt> threads will be active processing tasks.
+     * {@code nThreads} threads will be active processing tasks.
      * If additional tasks are submitted when all threads are active,
      * they will wait in the queue until a thread is available.
      * If any thread terminates due to a failure during execution
@@ -64,10 +64,48 @@
     }
 
     /**
+     * Creates a thread pool that maintains enough threads to support
+     * the given parallelism level, and may use multiple queues to
+     * reduce contention. The parallelism level corresponds to the
+     * maximum number of threads actively engaged in, or available to
+     * engage in, task processing. The actual number of threads may
+     * grow and shrink dynamically. A work-stealing pool makes no
+     * guarantees about the order in which submitted tasks are
+     * executed.
+     *
+     * @param parallelism the targeted parallelism level
+     * @return the newly created thread pool
+     * @throws IllegalArgumentException if {@code parallelism <= 0}
+     * @since 1.8
+     * @hide
+     */
+    public static ExecutorService newWorkStealingPool(int parallelism) {
+        return new ForkJoinPool
+            (parallelism,
+             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+             null, true);
+    }
+
+    /**
+     * Creates a work-stealing thread pool using all
+     * {@link Runtime#availableProcessors available processors}
+     * as its target parallelism level.
+     * @return the newly created thread pool
+     * @since 1.8
+     * @hide
+     */
+    public static ExecutorService newWorkStealingPool() {
+        return new ForkJoinPool
+            (Runtime.getRuntime().availableProcessors(),
+             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+             null, true);
+    }
+
+    /**
      * Creates a thread pool that reuses a fixed number of threads
      * operating off a shared unbounded queue, using the provided
      * ThreadFactory to create new threads when needed.  At any point,
-     * at most <tt>nThreads</tt> threads will be active processing
+     * at most {@code nThreads} threads will be active processing
      * tasks.  If additional tasks are submitted when all threads are
      * active, they will wait in the queue until a thread is
      * available.  If any thread terminates due to a failure during
@@ -97,7 +135,7 @@
      * subsequent tasks.)  Tasks are guaranteed to execute
      * sequentially, and no more than one task will be active at any
      * given time. Unlike the otherwise equivalent
-     * <tt>newFixedThreadPool(1)</tt> the returned executor is
+     * {@code newFixedThreadPool(1)} the returned executor is
      * guaranteed not to be reconfigurable to use additional threads.
      *
      * @return the newly created single-threaded Executor
@@ -113,7 +151,7 @@
      * Creates an Executor that uses a single worker thread operating
      * off an unbounded queue, and uses the provided ThreadFactory to
      * create a new thread when needed. Unlike the otherwise
-     * equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the
+     * equivalent {@code newFixedThreadPool(1, threadFactory)} the
      * returned executor is guaranteed not to be reconfigurable to use
      * additional threads.
      *
@@ -136,7 +174,7 @@
      * will reuse previously constructed threads when they are
      * available.  These pools will typically improve the performance
      * of programs that execute many short-lived asynchronous tasks.
-     * Calls to <tt>execute</tt> will reuse previously constructed
+     * Calls to {@code execute} will reuse previously constructed
      * threads if available. If no existing thread is available, a new
      * thread will be created and added to the pool. Threads that have
      * not been used for sixty seconds are terminated and removed from
@@ -178,7 +216,7 @@
      * subsequent tasks.)  Tasks are guaranteed to execute
      * sequentially, and no more than one task will be active at any
      * given time. Unlike the otherwise equivalent
-     * <tt>newScheduledThreadPool(1)</tt> the returned executor is
+     * {@code newScheduledThreadPool(1)} the returned executor is
      * guaranteed not to be reconfigurable to use additional threads.
      * @return the newly created scheduled executor
      */
@@ -195,7 +233,7 @@
      * place if needed to execute subsequent tasks.)  Tasks are
      * guaranteed to execute sequentially, and no more than one task
      * will be active at any given time. Unlike the otherwise
-     * equivalent <tt>newScheduledThreadPool(1, threadFactory)</tt>
+     * equivalent {@code newScheduledThreadPool(1, threadFactory)}
      * the returned executor is guaranteed not to be reconfigurable to
      * use additional threads.
      * @param threadFactory the factory to use when creating new
@@ -212,7 +250,7 @@
      * Creates a thread pool that can schedule commands to run after a
      * given delay, or to execute periodically.
      * @param corePoolSize the number of threads to keep in the pool,
-     * even if they are idle.
+     * even if they are idle
      * @return a newly created scheduled thread pool
      * @throws IllegalArgumentException if {@code corePoolSize < 0}
      */
@@ -224,9 +262,9 @@
      * Creates a thread pool that can schedule commands to run after a
      * given delay, or to execute periodically.
      * @param corePoolSize the number of threads to keep in the pool,
-     * even if they are idle.
+     * even if they are idle
      * @param threadFactory the factory to use when the executor
-     * creates a new thread.
+     * creates a new thread
      * @return a newly created scheduled thread pool
      * @throws IllegalArgumentException if {@code corePoolSize < 0}
      * @throws NullPointerException if threadFactory is null
@@ -236,7 +274,6 @@
         return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
     }
 
-
     /**
      * Returns an object that delegates all defined {@link
      * ExecutorService} methods to the given executor, but not any
@@ -244,7 +281,7 @@
      * casts. This provides a way to safely "freeze" configuration and
      * disallow tuning of a given concrete implementation.
      * @param executor the underlying implementation
-     * @return an <tt>ExecutorService</tt> instance
+     * @return an {@code ExecutorService} instance
      * @throws NullPointerException if executor null
      */
     public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
@@ -260,7 +297,7 @@
      * casts. This provides a way to safely "freeze" configuration and
      * disallow tuning of a given concrete implementation.
      * @param executor the underlying implementation
-     * @return a <tt>ScheduledExecutorService</tt> instance
+     * @return a {@code ScheduledExecutorService} instance
      * @throws NullPointerException if executor null
      */
     public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
@@ -274,7 +311,7 @@
      * This factory creates all new threads used by an Executor in the
      * same {@link ThreadGroup}. Each new
      * thread is created as a non-daemon thread with priority set to
-     * the smaller of <tt>Thread.NORM_PRIORITY</tt> and the maximum
+     * the smaller of {@code Thread.NORM_PRIORITY} and the maximum
      * priority permitted in the thread group.  New threads have names
      * accessible via {@link Thread#getName} of
      * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
@@ -297,7 +334,7 @@
      * Returns a {@link Callable} object that, when
      * called, runs the given task and returns the given result.  This
      * can be useful when applying methods requiring a
-     * <tt>Callable</tt> to an otherwise resultless action.
+     * {@code Callable} to an otherwise resultless action.
      * @param task the task to run
      * @param result the result to return
      * @return a callable object
@@ -311,7 +348,7 @@
 
     /**
      * Returns a {@link Callable} object that, when
-     * called, runs the given task and returns <tt>null</tt>.
+     * called, runs the given task and returns {@code null}.
      * @param task the task to run
      * @return a callable object
      * @throws NullPointerException if task null
@@ -361,12 +398,7 @@
     }
 
     /**
-     * Returns a {@link Callable} object that will, when
-     * called, execute the given <tt>callable</tt> under the current
-     * with the current context class loader as the context class loader.
-     *
-     * @return a callable object
-     * @throws NullPointerException if callable null
+     * Legacy security code; do not use.
      */
     public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable) {
         if (callable == null)
@@ -451,18 +483,17 @@
                 return AccessController.doPrivileged(
                     new PrivilegedExceptionAction<T>() {
                         public T run() throws Exception {
-                            ClassLoader savedcl = null;
                             Thread t = Thread.currentThread();
-                            try {
-                                ClassLoader cl = t.getContextClassLoader();
-                                if (ccl != cl) {
-                                    t.setContextClassLoader(ccl);
-                                    savedcl = cl;
-                                }
+                            ClassLoader cl = t.getContextClassLoader();
+                            if (ccl == cl) {
                                 return task.call();
-                            } finally {
-                                if (savedcl != null)
-                                    t.setContextClassLoader(savedcl);
+                            } else {
+                                t.setContextClassLoader(ccl);
+                                try {
+                                    return task.call();
+                                } finally {
+                                    t.setContextClassLoader(cl);
+                                }
                             }
                         }
                     }, acc);
@@ -609,21 +640,20 @@
             super(executor);
             e = executor;
         }
-        public ScheduledFuture<?> schedule(Runnable command, long delay,  TimeUnit unit) {
+        public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
             return e.schedule(command, delay, unit);
         }
         public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
             return e.schedule(callable, delay, unit);
         }
-        public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay,  long period, TimeUnit unit) {
+        public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
             return e.scheduleAtFixedRate(command, initialDelay, period, unit);
         }
-        public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,  long delay, TimeUnit unit) {
+        public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
             return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
         }
     }
 
-
     /** Cannot instantiate. */
     private Executors() {}
 }
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinPool.java b/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
index ee15ac8..87ffff3 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
@@ -11,7 +11,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.Random;
 import java.util.concurrent.AbstractExecutorService;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
@@ -19,15 +18,6 @@
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.RunnableFuture;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.locks.LockSupport;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.locks.Condition;
-import libcore.util.SneakyThrow;
-
-// BEGIN android-note
-// removed security manager docs
-// END android-note
 
 /**
  * An {@link ExecutorService} for running {@link ForkJoinTask}s.
@@ -38,21 +28,31 @@
  * <p>A {@code ForkJoinPool} differs from other kinds of {@link
  * ExecutorService} mainly by virtue of employing
  * <em>work-stealing</em>: all threads in the pool attempt to find and
- * execute subtasks created by other active tasks (eventually blocking
- * waiting for work if none exist). This enables efficient processing
- * when most tasks spawn other subtasks (as do most {@code
- * ForkJoinTask}s). When setting <em>asyncMode</em> to true in
- * constructors, {@code ForkJoinPool}s may also be appropriate for use
- * with event-style tasks that are never joined.
+ * execute tasks submitted to the pool and/or created by other active
+ * tasks (eventually blocking waiting for work if none exist). This
+ * enables efficient processing when most tasks spawn other subtasks
+ * (as do most {@code ForkJoinTask}s), as well as when many small
+ * tasks are submitted to the pool from external clients.  Especially
+ * when setting <em>asyncMode</em> to true in constructors, {@code
+ * ForkJoinPool}s may also be appropriate for use with event-style
+ * tasks that are never joined.
  *
- * <p>A {@code ForkJoinPool} is constructed with a given target
- * parallelism level; by default, equal to the number of available
- * processors. The pool attempts to maintain enough active (or
- * available) threads by dynamically adding, suspending, or resuming
- * internal worker threads, even if some tasks are stalled waiting to
- * join others. However, no such adjustments are guaranteed in the
- * face of blocked IO or other unmanaged synchronization. The nested
- * {@link ManagedBlocker} interface enables extension of the kinds of
+ * <p>A static {@link #commonPool()} is available and appropriate for
+ * most applications. The common pool is used by any ForkJoinTask that
+ * is not explicitly submitted to a specified pool. Using the common
+ * pool normally reduces resource usage (its threads are slowly
+ * reclaimed during periods of non-use, and reinstated upon subsequent
+ * use).
+ *
+ * <p>For applications that require separate or custom pools, a {@code
+ * ForkJoinPool} may be constructed with a given target parallelism
+ * level; by default, equal to the number of available processors. The
+ * pool attempts to maintain enough active (or available) threads by
+ * dynamically adding, suspending, or resuming internal worker
+ * threads, even if some tasks are stalled waiting to join
+ * others. However, no such adjustments are guaranteed in the face of
+ * blocked I/O or other unmanaged synchronization. The nested {@link
+ * ManagedBlocker} interface enables extension of the kinds of
  * synchronization accommodated.
  *
  * <p>In addition to execution and lifecycle control methods, this
@@ -62,16 +62,17 @@
  * {@link #toString} returns indications of pool state in a
  * convenient form for informal monitoring.
  *
- * <p> As is the case with other ExecutorServices, there are three
- * main task execution methods summarized in the following
- * table. These are designed to be used by clients not already engaged
- * in fork/join computations in the current pool.  The main forms of
- * these methods accept instances of {@code ForkJoinTask}, but
- * overloaded forms also allow mixed execution of plain {@code
+ * <p>As is the case with other ExecutorServices, there are three
+ * main task execution methods summarized in the following table.
+ * These are designed to be used primarily by clients not already
+ * engaged in fork/join computations in the current pool.  The main
+ * forms of these methods accept instances of {@code ForkJoinTask},
+ * but overloaded forms also allow mixed execution of plain {@code
  * Runnable}- or {@code Callable}- based activities as well.  However,
- * tasks that are already executing in a pool should normally
- * <em>NOT</em> use these pool execution methods, but instead use the
- * within-computation forms listed in the table.
+ * tasks that are already executing in a pool should normally instead
+ * use the within-computation forms listed in the table unless using
+ * async event-style tasks that are not usually joined, in which case
+ * there is little difference among choice of methods.
  *
  * <table BORDER CELLPADDING=3 CELLSPACING=1>
  *  <tr>
@@ -96,22 +97,16 @@
  *  </tr>
  * </table>
  *
- * <p><b>Sample Usage.</b> Normally a single {@code ForkJoinPool} is
- * used for all parallel task execution in a program or subsystem.
- * Otherwise, use would not usually outweigh the construction and
- * bookkeeping overhead of creating a large set of threads. For
- * example, a common pool could be used for the {@code SortTasks}
- * illustrated in {@link RecursiveAction}. Because {@code
- * ForkJoinPool} uses threads in {@linkplain java.lang.Thread#isDaemon
- * daemon} mode, there is typically no need to explicitly {@link
- * #shutdown} such a pool upon program exit.
- *
- *  <pre> {@code
- * static final ForkJoinPool mainPool = new ForkJoinPool();
- * ...
- * public void sort(long[] array) {
- *   mainPool.invoke(new SortTask(array, 0, array.length));
- * }}</pre>
+ * <p>The common pool is by default constructed with default
+ * parameters, but these may be controlled by setting three {@link
+ * System#getProperty system properties} with prefix {@code
+ * java.util.concurrent.ForkJoinPool.common}: {@code parallelism} --
+ * an integer greater than zero, {@code threadFactory} -- the class
+ * name of a {@link ForkJoinWorkerThreadFactory}, and {@code
+ * exceptionHandler} -- the class name of a {@link
+ * java.lang.Thread.UncaughtExceptionHandler
+ * Thread.UncaughtExceptionHandler}. Upon any error in establishing
+ * these settings, default parameters are used.
  *
  * <p><b>Implementation notes</b>: This implementation restricts the
  * maximum number of running threads to 32767. Attempts to create
@@ -131,214 +126,388 @@
     /*
      * Implementation Overview
      *
-     * This class provides the central bookkeeping and control for a
-     * set of worker threads: Submissions from non-FJ threads enter
-     * into a submission queue. Workers take these tasks and typically
-     * split them into subtasks that may be stolen by other workers.
-     * Preference rules give first priority to processing tasks from
-     * their own queues (LIFO or FIFO, depending on mode), then to
-     * randomized FIFO steals of tasks in other worker queues, and
-     * lastly to new submissions.
+     * This class and its nested classes provide the main
+     * functionality and control for a set of worker threads:
+     * Submissions from non-FJ threads enter into submission queues.
+     * Workers take these tasks and typically split them into subtasks
+     * that may be stolen by other workers.  Preference rules give
+     * first priority to processing tasks from their own queues (LIFO
+     * or FIFO, depending on mode), then to randomized FIFO steals of
+     * tasks in other queues.
+     *
+     * WorkQueues
+     * ==========
+     *
+     * Most operations occur within work-stealing queues (in nested
+     * class WorkQueue).  These are special forms of Deques that
+     * support only three of the four possible end-operations -- push,
+     * pop, and poll (aka steal), under the further constraints that
+     * push and pop are called only from the owning thread (or, as
+     * extended here, under a lock), while poll may be called from
+     * other threads.  (If you are unfamiliar with them, you probably
+     * want to read Herlihy and Shavit's book "The Art of
+     * Multiprocessor programming", chapter 16 describing these in
+     * more detail before proceeding.)  The main work-stealing queue
+     * design is roughly similar to those in the papers "Dynamic
+     * Circular Work-Stealing Deque" by Chase and Lev, SPAA 2005
+     * (http://research.sun.com/scalable/pubs/index.html) and
+     * "Idempotent work stealing" by Michael, Saraswat, and Vechev,
+     * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
+     * The main differences ultimately stem from GC requirements that
+     * we null out taken slots as soon as we can, to maintain as small
+     * a footprint as possible even in programs generating huge
+     * numbers of tasks. To accomplish this, we shift the CAS
+     * arbitrating pop vs poll (steal) from being on the indices
+     * ("base" and "top") to the slots themselves.  So, both a
+     * successful pop and poll mainly entail a CAS of a slot from
+     * non-null to null.  Because we rely on CASes of references, we
+     * do not need tag bits on base or top.  They are simple ints as
+     * used in any circular array-based queue (see for example
+     * ArrayDeque).  Updates to the indices must still be ordered in a
+     * way that guarantees that top == base means the queue is empty,
+     * but otherwise may err on the side of possibly making the queue
+     * appear nonempty when a push, pop, or poll have not fully
+     * committed. Note that this means that the poll operation,
+     * considered individually, is not wait-free. One thief cannot
+     * successfully continue until another in-progress one (or, if
+     * previously empty, a push) completes.  However, in the
+     * aggregate, we ensure at least probabilistic non-blockingness.
+     * If an attempted steal fails, a thief always chooses a different
+     * random victim target to try next. So, in order for one thief to
+     * progress, it suffices for any in-progress poll or new push on
+     * any empty queue to complete. (This is why we normally use
+     * method pollAt and its variants that try once at the apparent
+     * base index, else consider alternative actions, rather than
+     * method poll.)
+     *
+     * This approach also enables support of a user mode in which local
+     * task processing is in FIFO, not LIFO order, simply by using
+     * poll rather than pop.  This can be useful in message-passing
+     * frameworks in which tasks are never joined.  However neither
+     * mode considers affinities, loads, cache localities, etc, so
+     * rarely provide the best possible performance on a given
+     * machine, but portably provide good throughput by averaging over
+     * these factors.  (Further, even if we did try to use such
+     * information, we do not usually have a basis for exploiting it.
+     * For example, some sets of tasks profit from cache affinities,
+     * but others are harmed by cache pollution effects.)
+     *
+     * WorkQueues are also used in a similar way for tasks submitted
+     * to the pool. We cannot mix these tasks in the same queues used
+     * for work-stealing (this would contaminate lifo/fifo
+     * processing). Instead, we randomly associate submission queues
+     * with submitting threads, using a form of hashing.  The
+     * ThreadLocal Submitter class contains a value initially used as
+     * a hash code for choosing existing queues, but may be randomly
+     * repositioned upon contention with other submitters.  In
+     * essence, submitters act like workers except that they are
+     * restricted to executing local tasks that they submitted (or in
+     * the case of CountedCompleters, others with the same root task).
+     * However, because most shared/external queue operations are more
+     * expensive than internal, and because, at steady state, external
+     * submitters will compete for CPU with workers, ForkJoinTask.join
+     * and related methods disable them from repeatedly helping to
+     * process tasks if all workers are active.  Insertion of tasks in
+     * shared mode requires a lock (mainly to protect in the case of
+     * resizing) but we use only a simple spinlock (using bits in
+     * field qlock), because submitters encountering a busy queue move
+     * on to try or create other queues -- they block only when
+     * creating and registering new queues.
+     *
+     * Management
+     * ==========
      *
      * The main throughput advantages of work-stealing stem from
      * decentralized control -- workers mostly take tasks from
      * themselves or each other. We cannot negate this in the
      * implementation of other management responsibilities. The main
      * tactic for avoiding bottlenecks is packing nearly all
-     * essentially atomic control state into a single 64bit volatile
-     * variable ("ctl"). This variable is read on the order of 10-100
-     * times as often as it is modified (always via CAS). (There is
-     * some additional control state, for example variable "shutdown"
-     * for which we can cope with uncoordinated updates.)  This
-     * streamlines synchronization and control at the expense of messy
-     * constructions needed to repack status bits upon updates.
-     * Updates tend not to contend with each other except during
-     * bursts while submitted tasks begin or end.  In some cases when
-     * they do contend, threads can instead do something else
-     * (usually, scan for tasks) until contention subsides.
+     * essentially atomic control state into two volatile variables
+     * that are by far most often read (not written) as status and
+     * consistency checks.
      *
-     * To enable packing, we restrict maximum parallelism to (1<<15)-1
-     * (which is far in excess of normal operating range) to allow
-     * ids, counts, and their negations (used for thresholding) to fit
-     * into 16bit fields.
+     * Field "ctl" contains 64 bits holding all the information needed
+     * to atomically decide to add, inactivate, enqueue (on an event
+     * queue), dequeue, and/or re-activate workers.  To enable this
+     * packing, we restrict maximum parallelism to (1<<15)-1 (which is
+     * far in excess of normal operating range) to allow ids, counts,
+     * and their negations (used for thresholding) to fit into 16bit
+     * fields.
      *
-     * Recording Workers.  Workers are recorded in the "workers" array
-     * that is created upon pool construction and expanded if (rarely)
-     * necessary.  This is an array as opposed to some other data
-     * structure to support index-based random steals by workers.
-     * Updates to the array recording new workers and unrecording
-     * terminated ones are protected from each other by a seqLock
-     * (scanGuard) but the array is otherwise concurrently readable,
-     * and accessed directly by workers. To simplify index-based
-     * operations, the array size is always a power of two, and all
-     * readers must tolerate null slots. To avoid flailing during
-     * start-up, the array is presized to hold twice #parallelism
-     * workers (which is unlikely to need further resizing during
-     * execution). But to avoid dealing with so many null slots,
-     * variable scanGuard includes a mask for the nearest power of two
-     * that contains all current workers.  All worker thread creation
-     * is on-demand, triggered by task submissions, replacement of
-     * terminated workers, and/or compensation for blocked
-     * workers. However, all other support code is set up to work with
-     * other policies.  To ensure that we do not hold on to worker
-     * references that would prevent GC, ALL accesses to workers are
-     * via indices into the workers array (which is one source of some
-     * of the messy code constructions here). In essence, the workers
-     * array serves as a weak reference mechanism. Thus for example
-     * the wait queue field of ctl stores worker indices, not worker
-     * references.  Access to the workers in associated methods (for
-     * example signalWork) must both index-check and null-check the
-     * IDs. All such accesses ignore bad IDs by returning out early
-     * from what they are doing, since this can only be associated
-     * with termination, in which case it is OK to give up.
+     * Field "plock" is a form of sequence lock with a saturating
+     * shutdown bit (similarly for per-queue "qlocks"), mainly
+     * protecting updates to the workQueues array, as well as to
+     * enable shutdown.  When used as a lock, it is normally only very
+     * briefly held, so is nearly always available after at most a
+     * brief spin, but we use a monitor-based backup strategy to
+     * block when needed.
      *
-     * All uses of the workers array, as well as queue arrays, check
-     * that the array is non-null (even if previously non-null). This
-     * allows nulling during termination, which is currently not
-     * necessary, but remains an option for resource-revocation-based
-     * shutdown schemes.
+     * Recording WorkQueues.  WorkQueues are recorded in the
+     * "workQueues" array that is created upon first use and expanded
+     * if necessary.  Updates to the array while recording new workers
+     * and unrecording terminated ones are protected from each other
+     * by a lock but the array is otherwise concurrently readable, and
+     * accessed directly.  To simplify index-based operations, the
+     * array size is always a power of two, and all readers must
+     * tolerate null slots. Worker queues are at odd indices. Shared
+     * (submission) queues are at even indices, up to a maximum of 64
+     * slots, to limit growth even if array needs to expand to add
+     * more workers. Grouping them together in this way simplifies and
+     * speeds up task scanning.
      *
-     * Wait Queuing. Unlike HPC work-stealing frameworks, we cannot
+     * All worker thread creation is on-demand, triggered by task
+     * submissions, replacement of terminated workers, and/or
+     * compensation for blocked workers. However, all other support
+     * code is set up to work with other policies.  To ensure that we
+     * do not hold on to worker references that would prevent GC, ALL
+     * accesses to workQueues are via indices into the workQueues
+     * array (which is one source of some of the messy code
+     * constructions here). In essence, the workQueues array serves as
+     * a weak reference mechanism. Thus for example the wait queue
+     * field of ctl stores indices, not references.  Access to the
+     * workQueues in associated methods (for example signalWork) must
+     * both index-check and null-check the IDs. All such accesses
+     * ignore bad IDs by returning out early from what they are doing,
+     * since this can only be associated with termination, in which
+     * case it is OK to give up.  All uses of the workQueues array
+     * also check that it is non-null (even if previously
+     * non-null). This allows nulling during termination, which is
+     * currently not necessary, but remains an option for
+     * resource-revocation-based shutdown schemes. It also helps
+     * reduce JIT issuance of uncommon-trap code, which tends to
+     * unnecessarily complicate control flow in some methods.
+     *
+     * Event Queuing. Unlike HPC work-stealing frameworks, we cannot
      * let workers spin indefinitely scanning for tasks when none can
      * be found immediately, and we cannot start/resume workers unless
      * there appear to be tasks available.  On the other hand, we must
      * quickly prod them into action when new tasks are submitted or
-     * generated.  We park/unpark workers after placing in an event
-     * wait queue when they cannot find work. This "queue" is actually
-     * a simple Treiber stack, headed by the "id" field of ctl, plus a
-     * 15bit counter value to both wake up waiters (by advancing their
-     * count) and avoid ABA effects. Successors are held in worker
-     * field "nextWait".  Queuing deals with several intrinsic races,
-     * mainly that a task-producing thread can miss seeing (and
+     * generated. In many usages, ramp-up time to activate workers is
+     * the main limiting factor in overall performance (this is
+     * compounded at program start-up by JIT compilation and
+     * allocation). So we try to streamline this as much as possible.
+     * We park/unpark workers after placing in an event wait queue
+     * when they cannot find work. This "queue" is actually a simple
+     * Treiber stack, headed by the "id" field of ctl, plus a 15bit
+     * counter value (that reflects the number of times a worker has
+     * been inactivated) to avoid ABA effects (we need only as many
+     * version numbers as worker threads). Successors are held in
+     * field WorkQueue.nextWait.  Queuing deals with several intrinsic
+     * races, mainly that a task-producing thread can miss seeing (and
      * signalling) another thread that gave up looking for work but
      * has not yet entered the wait queue. We solve this by requiring
-     * a full sweep of all workers both before (in scan()) and after
-     * (in tryAwaitWork()) a newly waiting worker is added to the wait
-     * queue. During a rescan, the worker might release some other
-     * queued worker rather than itself, which has the same net
-     * effect. Because enqueued workers may actually be rescanning
-     * rather than waiting, we set and clear the "parked" field of
-     * ForkJoinWorkerThread to reduce unnecessary calls to unpark.
-     * (Use of the parked field requires a secondary recheck to avoid
-     * missed signals.)
+     * a full sweep of all workers (via repeated calls to method
+     * scan()) both before and after a newly waiting worker is added
+     * to the wait queue. During a rescan, the worker might release
+     * some other queued worker rather than itself, which has the same
+     * net effect. Because enqueued workers may actually be rescanning
+     * rather than waiting, we set and clear the "parker" field of
+     * WorkQueues to reduce unnecessary calls to unpark.  (This
+     * requires a secondary recheck to avoid missed signals.)  Note
+     * the unusual conventions about Thread.interrupts surrounding
+     * parking and other blocking: Because interrupts are used solely
+     * to alert threads to check termination, which is checked anyway
+     * upon blocking, we clear status (using Thread.interrupted)
+     * before any call to park, so that park does not immediately
+     * return due to status being set via some other unrelated call to
+     * interrupt in user code.
      *
      * Signalling.  We create or wake up workers only when there
      * appears to be at least one task they might be able to find and
-     * execute.  When a submission is added or another worker adds a
-     * task to a queue that previously had two or fewer tasks, they
-     * signal waiting workers (or trigger creation of new ones if
-     * fewer than the given parallelism level -- see signalWork).
-     * These primary signals are buttressed by signals during rescans
-     * as well as those performed when a worker steals a task and
-     * notices that there are more tasks too; together these cover the
-     * signals needed in cases when more than two tasks are pushed
-     * but untaken.
+     * execute. However, many other threads may notice the same task
+     * and each signal to wake up a thread that might take it. So in
+     * general, pools will be over-signalled.  When a submission is
+     * added or another worker adds a task to a queue that has fewer
+     * than two tasks, they signal waiting workers (or trigger
+     * creation of new ones if fewer than the given parallelism level
+     * -- signalWork), and may leave a hint to the unparked worker to
+     * help signal others upon wakeup).  These primary signals are
+     * buttressed by others (see method helpSignal) whenever other
+     * threads scan for work or do not have a task to process.  On
+     * most platforms, signalling (unpark) overhead time is noticeably
+     * long, and the time between signalling a thread and it actually
+     * making progress can be very noticeably long, so it is worth
+     * offloading these delays from critical paths as much as
+     * possible.
      *
      * Trimming workers. To release resources after periods of lack of
      * use, a worker starting to wait when the pool is quiescent will
-     * time out and terminate if the pool has remained quiescent for
-     * SHRINK_RATE nanosecs. This will slowly propagate, eventually
-     * terminating all workers after long periods of non-use.
+     * time out and terminate if the pool has remained quiescent for a
+     * given period -- a short period if there are more threads than
+     * parallelism, longer as the number of threads decreases. This
+     * will slowly propagate, eventually terminating all workers after
+     * periods of non-use.
      *
-     * Submissions. External submissions are maintained in an
-     * array-based queue that is structured identically to
-     * ForkJoinWorkerThread queues except for the use of
-     * submissionLock in method addSubmission. Unlike the case for
-     * worker queues, multiple external threads can add new
-     * submissions, so adding requires a lock.
+     * Shutdown and Termination. A call to shutdownNow atomically sets
+     * a plock bit and then (non-atomically) sets each worker's
+     * qlock status, cancels all unprocessed tasks, and wakes up
+     * all waiting workers.  Detecting whether termination should
+     * commence after a non-abrupt shutdown() call requires more work
+     * and bookkeeping. We need consensus about quiescence (i.e., that
+     * there is no more work). The active count provides a primary
+     * indication but non-abrupt shutdown still requires a rechecking
+     * scan for any workers that are inactive but not queued.
      *
-     * Compensation. Beyond work-stealing support and lifecycle
-     * control, the main responsibility of this framework is to take
-     * actions when one worker is waiting to join a task stolen (or
-     * always held by) another.  Because we are multiplexing many
-     * tasks on to a pool of workers, we can't just let them block (as
-     * in Thread.join).  We also cannot just reassign the joiner's
-     * run-time stack with another and replace it later, which would
-     * be a form of "continuation", that even if possible is not
-     * necessarily a good idea since we sometimes need both an
-     * unblocked task and its continuation to progress. Instead we
-     * combine two tactics:
+     * Joining Tasks
+     * =============
+     *
+     * Any of several actions may be taken when one worker is waiting
+     * to join a task stolen (or always held) by another.  Because we
+     * are multiplexing many tasks on to a pool of workers, we can't
+     * just let them block (as in Thread.join).  We also cannot just
+     * reassign the joiner's run-time stack with another and replace
+     * it later, which would be a form of "continuation", that even if
+     * possible is not necessarily a good idea since we sometimes need
+     * both an unblocked task and its continuation to progress.
+     * Instead we combine two tactics:
      *
      *   Helping: Arranging for the joiner to execute some task that it
-     *      would be running if the steal had not occurred.  Method
-     *      ForkJoinWorkerThread.joinTask tracks joining->stealing
-     *      links to try to find such a task.
+     *      would be running if the steal had not occurred.
      *
      *   Compensating: Unless there are already enough live threads,
-     *      method tryPreBlock() may create or re-activate a spare
-     *      thread to compensate for blocked joiners until they
-     *      unblock.
+     *      method tryCompensate() may create or re-activate a spare
+     *      thread to compensate for blocked joiners until they unblock.
+     *
+     * A third form (implemented in tryRemoveAndExec) amounts to
+     * helping a hypothetical compensator: If we can readily tell that
+     * a possible action of a compensator is to steal and execute the
+     * task being joined, the joining thread can do so directly,
+     * without the need for a compensation thread (although at the
+     * expense of larger run-time stacks, but the tradeoff is
+     * typically worthwhile).
      *
      * The ManagedBlocker extension API can't use helping so relies
      * only on compensation in method awaitBlocker.
      *
+     * The algorithm in tryHelpStealer entails a form of "linear"
+     * helping: Each worker records (in field currentSteal) the most
+     * recent task it stole from some other worker. Plus, it records
+     * (in field currentJoin) the task it is currently actively
+     * joining. Method tryHelpStealer uses these markers to try to
+     * find a worker to help (i.e., steal back a task from and execute
+     * it) that could hasten completion of the actively joined task.
+     * In essence, the joiner executes a task that would be on its own
+     * local deque had the to-be-joined task not been stolen. This may
+     * be seen as a conservative variant of the approach in Wagner &
+     * Calder "Leapfrogging: a portable technique for implementing
+     * efficient futures" SIGPLAN Notices, 1993
+     * (http://portal.acm.org/citation.cfm?id=155354). It differs in
+     * that: (1) We only maintain dependency links across workers upon
+     * steals, rather than use per-task bookkeeping.  This sometimes
+     * requires a linear scan of workQueues array to locate stealers,
+     * but often doesn't because stealers leave hints (that may become
+     * stale/wrong) of where to locate them.  It is only a hint
+     * because a worker might have had multiple steals and the hint
+     * records only one of them (usually the most current).  Hinting
+     * isolates cost to when it is needed, rather than adding to
+     * per-task overhead.  (2) It is "shallow", ignoring nesting and
+     * potentially cyclic mutual steals.  (3) It is intentionally
+     * racy: field currentJoin is updated only while actively joining,
+     * which means that we miss links in the chain during long-lived
+     * tasks, GC stalls etc (which is OK since blocking in such cases
+     * is usually a good idea).  (4) We bound the number of attempts
+     * to find work (see MAX_HELP) and fall back to suspending the
+     * worker and if necessary replacing it with another.
+     *
+     * Helping actions for CountedCompleters are much simpler: Method
+     * helpComplete can take and execute any task with the same root
+     * as the task being waited on. However, this still entails some
+     * traversal of completer chains, so is less efficient than using
+     * CountedCompleters without explicit joins.
+     *
      * It is impossible to keep exactly the target parallelism number
      * of threads running at any given time.  Determining the
      * existence of conservatively safe helping targets, the
      * availability of already-created spares, and the apparent need
-     * to create new spares are all racy and require heuristic
-     * guidance, so we rely on multiple retries of each.  Currently,
-     * in keeping with on-demand signalling policy, we compensate only
-     * if blocking would leave less than one active (non-waiting,
-     * non-blocked) worker. Additionally, to avoid some false alarms
-     * due to GC, lagging counters, system activity, etc, compensated
-     * blocking for joins is only attempted after rechecks stabilize
-     * (retries are interspersed with Thread.yield, for good
-     * citizenship).  The variable blockedCount, incremented before
-     * blocking and decremented after, is sometimes needed to
-     * distinguish cases of waiting for work vs blocking on joins or
-     * other managed sync. Both cases are equivalent for most pool
-     * control, so we can update non-atomically. (Additionally,
-     * contention on blockedCount alleviates some contention on ctl).
+     * to create new spares are all racy, so we rely on multiple
+     * retries of each.  Compensation in the apparent absence of
+     * helping opportunities is challenging to control on JVMs, where
+     * GC and other activities can stall progress of tasks that in
+     * turn stall out many other dependent tasks, without us being
+     * able to determine whether they will ever require compensation.
+     * Even though work-stealing otherwise encounters little
+     * degradation in the presence of more threads than cores,
+     * aggressively adding new threads in such cases entails risk of
+     * unwanted positive feedback control loops in which more threads
+     * cause more dependent stalls (as well as delayed progress of
+     * unblocked threads to the point that we know they are available)
+     * leading to more situations requiring more threads, and so
+     * on. This aspect of control can be seen as an (analytically
+     * intractable) game with an opponent that may choose the worst
+     * (for us) active thread to stall at any time.  We take several
+     * precautions to bound losses (and thus bound gains), mainly in
+     * methods tryCompensate and awaitJoin.
      *
-     * Shutdown and Termination. A call to shutdownNow atomically sets
-     * the ctl stop bit and then (non-atomically) sets each workers
-     * "terminate" status, cancels all unprocessed tasks, and wakes up
-     * all waiting workers.  Detecting whether termination should
-     * commence after a non-abrupt shutdown() call requires more work
-     * and bookkeeping. We need consensus about quiescence (i.e., that
-     * there is no more work) which is reflected in active counts so
-     * long as there are no current blockers, as well as possible
-     * re-evaluations during independent changes in blocking or
-     * quiescing workers.
+     * Common Pool
+     * ===========
      *
-     * Style notes: There is a lot of representation-level coupling
-     * among classes ForkJoinPool, ForkJoinWorkerThread, and
-     * ForkJoinTask.  Most fields of ForkJoinWorkerThread maintain
-     * data structures managed by ForkJoinPool, so are directly
-     * accessed.  Conversely we allow access to "workers" array by
-     * workers, and direct access to ForkJoinTask.status by both
-     * ForkJoinPool and ForkJoinWorkerThread.  There is little point
+     * The static commonPool always exists after static
+     * initialization.  Since it (or any other created pool) need
+     * never be used, we minimize initial construction overhead and
+     * footprint to the setup of about a dozen fields, with no nested
+     * allocation. Most bootstrapping occurs within method
+     * fullExternalPush during the first submission to the pool.
+     *
+     * When external threads submit to the common pool, they can
+     * perform some subtask processing (see externalHelpJoin and
+     * related methods).  We do not need to record whether these
+     * submissions are to the common pool -- if not, externalHelpJoin
+     * returns quickly (at the most helping to signal some common pool
+     * workers). These submitters would otherwise be blocked waiting
+     * for completion, so the extra effort (with liberally sprinkled
+     * task status checks) in inapplicable cases amounts to an odd
+     * form of limited spin-wait before blocking in ForkJoinTask.join.
+     *
+     * Style notes
+     * ===========
+     *
+     * There is a lot of representation-level coupling among classes
+     * ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask.  The
+     * fields of WorkQueue maintain data structures managed by
+     * ForkJoinPool, so are directly accessed.  There is little point
      * trying to reduce this, since any associated future changes in
      * representations will need to be accompanied by algorithmic
-     * changes anyway. All together, these low-level implementation
-     * choices produce as much as a factor of 4 performance
-     * improvement compared to naive implementations, and enable the
-     * processing of billions of tasks per second, at the expense of
-     * some ugliness.
+     * changes anyway. Several methods intrinsically sprawl because
+     * they must accumulate sets of consistent reads of volatiles held
+     * in local variables.  Methods signalWork() and scan() are the
+     * main bottlenecks, so are especially heavily
+     * micro-optimized/mangled.  There are lots of inline assignments
+     * (of form "while ((local = field) != 0)") which are usually the
+     * simplest way to ensure the required read orderings (which are
+     * sometimes critical). This leads to a "C"-like style of listing
+     * declarations of these locals at the heads of methods or blocks.
+     * There are several occurrences of the unusual "do {} while
+     * (!cas...)"  which is the simplest way to force an update of a
+     * CAS'ed variable. There are also other coding oddities (including
+     * several unnecessary-looking hoisted null checks) that help
+     * some methods perform reasonably even when interpreted (not
+     * compiled).
      *
-     * Methods signalWork() and scan() are the main bottlenecks so are
-     * especially heavily micro-optimized/mangled.  There are lots of
-     * inline assignments (of form "while ((local = field) != 0)")
-     * which are usually the simplest way to ensure the required read
-     * orderings (which are sometimes critical). This leads to a
-     * "C"-like style of listing declarations of these locals at the
-     * heads of methods or blocks.  There are several occurrences of
-     * the unusual "do {} while (!cas...)"  which is the simplest way
-     * to force an update of a CAS'ed variable. There are also other
-     * coding oddities that help some methods perform reasonably even
-     * when interpreted (not compiled).
-     *
-     * The order of declarations in this file is: (1) declarations of
-     * statics (2) fields (along with constants used when unpacking
-     * some of them), listed in an order that tends to reduce
-     * contention among them a bit under most JVMs.  (3) internal
-     * control methods (4) callbacks and other support for
-     * ForkJoinTask and ForkJoinWorkerThread classes, (5) exported
-     * methods (plus a few little helpers). (6) static block
-     * initializing all statics in a minimally dependent order.
+     * The order of declarations in this file is:
+     * (1) Static utility functions
+     * (2) Nested (static) classes
+     * (3) Static fields
+     * (4) Fields, along with constants used when unpacking some of them
+     * (5) Internal control methods
+     * (6) Callbacks and other support for ForkJoinTask methods
+     * (7) Exported methods
+     * (8) Static block initializing statics in minimally dependent order
      */
 
+    // Static utilities
+
+    /**
+     * If there is a security manager, makes sure caller has
+     * permission to modify threads.
+     */
+    private static void checkPermission() {
+        SecurityManager security = System.getSecurityManager();
+        if (security != null)
+            security.checkPermission(modifyThreadPermission);
+    }
+
+    // Nested classes
+
     /**
      * Factory for creating new {@link ForkJoinWorkerThread}s.
      * A {@code ForkJoinWorkerThreadFactory} must be defined and used
@@ -359,14 +528,525 @@
      * Default ForkJoinWorkerThreadFactory implementation; creates a
      * new ForkJoinWorkerThread.
      */
-    static class DefaultForkJoinWorkerThreadFactory
+    static final class DefaultForkJoinWorkerThreadFactory
         implements ForkJoinWorkerThreadFactory {
-        public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
+        public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
             return new ForkJoinWorkerThread(pool);
         }
     }
 
     /**
+     * Per-thread records for threads that submit to pools. Currently
+     * holds only pseudo-random seed / index that is used to choose
+     * submission queues in method externalPush. In the future, this may
+     * also incorporate a means to implement different task rejection
+     * and resubmission policies.
+     *
+     * Seeds for submitters and workers/workQueues work in basically
+     * the same way but are initialized and updated using slightly
+     * different mechanics. Both are initialized using the same
+     * approach as in class ThreadLocal, where successive values are
+     * unlikely to collide with previous values. Seeds are then
+     * randomly modified upon collisions using xorshifts, which
+     * requires a non-zero seed.
+     */
+    static final class Submitter {
+        int seed;
+        Submitter(int s) { seed = s; }
+    }
+
+    /**
+     * Class for artificial tasks that are used to replace the target
+     * of local joins if they are removed from an interior queue slot
+     * in WorkQueue.tryRemoveAndExec. We don't need the proxy to
+     * actually do anything beyond having a unique identity.
+     */
+    static final class EmptyTask extends ForkJoinTask<Void> {
+        private static final long serialVersionUID = -7721805057305804111L;
+        EmptyTask() { status = ForkJoinTask.NORMAL; } // force done
+        public final Void getRawResult() { return null; }
+        public final void setRawResult(Void x) {}
+        public final boolean exec() { return true; }
+    }
+
+    /**
+     * Queues supporting work-stealing as well as external task
+     * submission. See above for main rationale and algorithms.
+     * Implementation relies heavily on "Unsafe" intrinsics
+     * and selective use of "volatile":
+     *
+     * Field "base" is the index (mod array.length) of the least valid
+     * queue slot, which is always the next position to steal (poll)
+     * from if nonempty. Reads and writes require volatile orderings
+     * but not CAS, because updates are only performed after slot
+     * CASes.
+     *
+     * Field "top" is the index (mod array.length) of the next queue
+     * slot to push to or pop from. It is written only by owner thread
+     * for push, or under lock for external/shared push, and accessed
+     * by other threads only after reading (volatile) base.  Both top
+     * and base are allowed to wrap around on overflow, but (top -
+     * base) (or more commonly -(base - top) to force volatile read of
+     * base before top) still estimates size. The lock ("qlock") is
+     * forced to -1 on termination, causing all further lock attempts
+     * to fail. (Note: we don't need CAS for termination state because
+     * upon pool shutdown, all shared-queues will stop being used
+     * anyway.)  Nearly all lock bodies are set up so that exceptions
+     * within lock bodies are "impossible" (modulo JVM errors that
+     * would cause failure anyway.)
+     *
+     * The array slots are read and written using the emulation of
+     * volatiles/atomics provided by Unsafe. Insertions must in
+     * general use putOrderedObject as a form of releasing store to
+     * ensure that all writes to the task object are ordered before
+     * its publication in the queue.  All removals entail a CAS to
+     * null.  The array is always a power of two. To ensure safety of
+     * Unsafe array operations, all accesses perform explicit null
+     * checks and implicit bounds checks via power-of-two masking.
+     *
+     * In addition to basic queuing support, this class contains
+     * fields described elsewhere to control execution. It turns out
+     * to work better memory-layout-wise to include them in this class
+     * rather than a separate class.
+     *
+     * Performance on most platforms is very sensitive to placement of
+     * instances of both WorkQueues and their arrays -- we absolutely
+     * do not want multiple WorkQueue instances or multiple queue
+     * arrays sharing cache lines. (It would be best for queue objects
+     * and their arrays to share, but there is nothing available to
+     * help arrange that).  Unfortunately, because they are recorded
+     * in a common array, WorkQueue instances are often moved to be
+     * adjacent by garbage collectors. To reduce impact, we use field
+     * padding that works OK on common platforms; this effectively
+     * trades off slightly slower average field access for the sake of
+     * avoiding really bad worst-case access. (Until better JVM
+     * support is in place, this padding is dependent on transient
+     * properties of JVM field layout rules.) We also take care in
+     * allocating, sizing and resizing the array. Non-shared queue
+     * arrays are initialized by workers before use. Others are
+     * allocated on first use.
+     */
+    static final class WorkQueue {
+        /**
+         * Capacity of work-stealing queue array upon initialization.
+         * Must be a power of two; at least 4, but should be larger to
+         * reduce or eliminate cacheline sharing among queues.
+         * Currently, it is much larger, as a partial workaround for
+         * the fact that JVMs often place arrays in locations that
+         * share GC bookkeeping (especially cardmarks) such that
+         * per-write accesses encounter serious memory contention.
+         */
+        static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
+
+        /**
+         * Maximum size for queue arrays. Must be a power of two less
+         * than or equal to 1 << (31 - width of array entry) to ensure
+         * lack of wraparound of index calculations, but defined to a
+         * value a bit less than this to help users trap runaway
+         * programs before saturating systems.
+         */
+        static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
+
+        // Heuristic padding to ameliorate unfortunate memory placements
+        volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06;
+
+        int seed;                  // for random scanning; initialize nonzero
+        volatile int eventCount;   // encoded inactivation count; < 0 if inactive
+        int nextWait;              // encoded record of next event waiter
+        int hint;                  // steal or signal hint (index)
+        int poolIndex;             // index of this queue in pool (or 0)
+        final int mode;            // 0: lifo, > 0: fifo, < 0: shared
+        int nsteals;               // number of steals
+        volatile int qlock;        // 1: locked, -1: terminate; else 0
+        volatile int base;         // index of next slot for poll
+        int top;                   // index of next slot for push
+        ForkJoinTask<?>[] array;   // the elements (initially unallocated)
+        final ForkJoinPool pool;   // the containing pool (may be null)
+        final ForkJoinWorkerThread owner; // owning thread or null if shared
+        volatile Thread parker;    // == owner during call to park; else null
+        volatile ForkJoinTask<?> currentJoin;  // task being joined in awaitJoin
+        ForkJoinTask<?> currentSteal; // current non-local task being executed
+
+        volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17;
+        volatile Object pad18, pad19, pad1a, pad1b, pad1c, pad1d;
+
+        WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner, int mode,
+                  int seed) {
+            this.pool = pool;
+            this.owner = owner;
+            this.mode = mode;
+            this.seed = seed;
+            // Place indices in the center of array (that is not yet allocated)
+            base = top = INITIAL_QUEUE_CAPACITY >>> 1;
+        }
+
+        /**
+         * Returns the approximate number of tasks in the queue.
+         */
+        final int queueSize() {
+            int n = base - top;       // non-owner callers must read base first
+            return (n >= 0) ? 0 : -n; // ignore transient negative
+        }
+
+       /**
+         * Provides a more accurate estimate of whether this queue has
+         * any tasks than does queueSize, by checking whether a
+         * near-empty queue has at least one unclaimed task.
+         */
+        final boolean isEmpty() {
+            ForkJoinTask<?>[] a; int m, s;
+            int n = base - (s = top);
+            return (n >= 0 ||
+                    (n == -1 &&
+                     ((a = array) == null ||
+                      (m = a.length - 1) < 0 ||
+                      U.getObject
+                      (a, (long)((m & (s - 1)) << ASHIFT) + ABASE) == null)));
+        }
+
+        /**
+         * Pushes a task. Call only by owner in unshared queues.  (The
+         * shared-queue version is embedded in method externalPush.)
+         *
+         * @param task the task. Caller must ensure non-null.
+         * @throws RejectedExecutionException if array cannot be resized
+         */
+        final void push(ForkJoinTask<?> task) {
+            ForkJoinTask<?>[] a; ForkJoinPool p;
+            int s = top, m, n;
+            if ((a = array) != null) {    // ignore if queue removed
+                int j = (((m = a.length - 1) & s) << ASHIFT) + ABASE;
+                U.putOrderedObject(a, j, task);
+                if ((n = (top = s + 1) - base) <= 2) {
+                    if ((p = pool) != null)
+                        p.signalWork(this);
+                }
+                else if (n >= m)
+                    growArray();
+            }
+        }
+
+       /**
+         * Initializes or doubles the capacity of array. Call either
+         * by owner or with lock held -- it is OK for base, but not
+         * top, to move while resizings are in progress.
+         */
+        final ForkJoinTask<?>[] growArray() {
+            ForkJoinTask<?>[] oldA = array;
+            int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY;
+            if (size > MAXIMUM_QUEUE_CAPACITY)
+                throw new RejectedExecutionException("Queue capacity exceeded");
+            int oldMask, t, b;
+            ForkJoinTask<?>[] a = array = new ForkJoinTask<?>[size];
+            if (oldA != null && (oldMask = oldA.length - 1) >= 0 &&
+                (t = top) - (b = base) > 0) {
+                int mask = size - 1;
+                do {
+                    ForkJoinTask<?> x;
+                    int oldj = ((b & oldMask) << ASHIFT) + ABASE;
+                    int j    = ((b &    mask) << ASHIFT) + ABASE;
+                    x = (ForkJoinTask<?>)U.getObjectVolatile(oldA, oldj);
+                    if (x != null &&
+                        U.compareAndSwapObject(oldA, oldj, x, null))
+                        U.putObjectVolatile(a, j, x);
+                } while (++b != t);
+            }
+            return a;
+        }
+
+        /**
+         * Takes next task, if one exists, in LIFO order.  Call only
+         * by owner in unshared queues.
+         */
+        final ForkJoinTask<?> pop() {
+            ForkJoinTask<?>[] a; ForkJoinTask<?> t; int m;
+            if ((a = array) != null && (m = a.length - 1) >= 0) {
+                for (int s; (s = top - 1) - base >= 0;) {
+                    long j = ((m & s) << ASHIFT) + ABASE;
+                    if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
+                        break;
+                    if (U.compareAndSwapObject(a, j, t, null)) {
+                        top = s;
+                        return t;
+                    }
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Takes a task in FIFO order if b is base of queue and a task
+         * can be claimed without contention. Specialized versions
+         * appear in ForkJoinPool methods scan and tryHelpStealer.
+         */
+        final ForkJoinTask<?> pollAt(int b) {
+            ForkJoinTask<?> t; ForkJoinTask<?>[] a;
+            if ((a = array) != null) {
+                int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null &&
+                    base == b &&
+                    U.compareAndSwapObject(a, j, t, null)) {
+                    base = b + 1;
+                    return t;
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Takes next task, if one exists, in FIFO order.
+         */
+        final ForkJoinTask<?> poll() {
+            ForkJoinTask<?>[] a; int b; ForkJoinTask<?> t;
+            while ((b = base) - top < 0 && (a = array) != null) {
+                int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
+                if (t != null) {
+                    if (base == b &&
+                        U.compareAndSwapObject(a, j, t, null)) {
+                        base = b + 1;
+                        return t;
+                    }
+                }
+                else if (base == b) {
+                    if (b + 1 == top)
+                        break;
+                    Thread.yield(); // wait for lagging update (very rare)
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Takes next task, if one exists, in order specified by mode.
+         */
+        final ForkJoinTask<?> nextLocalTask() {
+            return mode == 0 ? pop() : poll();
+        }
+
+        /**
+         * Returns next task, if one exists, in order specified by mode.
+         */
+        final ForkJoinTask<?> peek() {
+            ForkJoinTask<?>[] a = array; int m;
+            if (a == null || (m = a.length - 1) < 0)
+                return null;
+            int i = mode == 0 ? top - 1 : base;
+            int j = ((i & m) << ASHIFT) + ABASE;
+            return (ForkJoinTask<?>)U.getObjectVolatile(a, j);
+        }
+
+        /**
+         * Pops the given task only if it is at the current top.
+         * (A shared version is available only via FJP.tryExternalUnpush)
+         */
+        final boolean tryUnpush(ForkJoinTask<?> t) {
+            ForkJoinTask<?>[] a; int s;
+            if ((a = array) != null && (s = top) != base &&
+                U.compareAndSwapObject
+                (a, (((a.length - 1) & --s) << ASHIFT) + ABASE, t, null)) {
+                top = s;
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Removes and cancels all known tasks, ignoring any exceptions.
+         */
+        final void cancelAll() {
+            ForkJoinTask.cancelIgnoringExceptions(currentJoin);
+            ForkJoinTask.cancelIgnoringExceptions(currentSteal);
+            for (ForkJoinTask<?> t; (t = poll()) != null; )
+                ForkJoinTask.cancelIgnoringExceptions(t);
+        }
+
+        /**
+         * Computes next value for random probes.  Scans don't require
+         * a very high quality generator, but also not a crummy one.
+         * Marsaglia xor-shift is cheap and works well enough.  Note:
+         * This is manually inlined in its usages in ForkJoinPool to
+         * avoid writes inside busy scan loops.
+         */
+        final int nextSeed() {
+            int r = seed;
+            r ^= r << 13;
+            r ^= r >>> 17;
+            return seed = r ^= r << 5;
+        }
+
+        // Specialized execution methods
+
+        /**
+         * Pops and runs tasks until empty.
+         */
+        private void popAndExecAll() {
+            // A bit faster than repeated pop calls
+            ForkJoinTask<?>[] a; int m, s; long j; ForkJoinTask<?> t;
+            while ((a = array) != null && (m = a.length - 1) >= 0 &&
+                   (s = top - 1) - base >= 0 &&
+                   (t = ((ForkJoinTask<?>)
+                         U.getObject(a, j = ((m & s) << ASHIFT) + ABASE)))
+                   != null) {
+                if (U.compareAndSwapObject(a, j, t, null)) {
+                    top = s;
+                    t.doExec();
+                }
+            }
+        }
+
+        /**
+         * Polls and runs tasks until empty.
+         */
+        private void pollAndExecAll() {
+            for (ForkJoinTask<?> t; (t = poll()) != null;)
+                t.doExec();
+        }
+
+        /**
+         * If present, removes from queue and executes the given task,
+         * or any other cancelled task. Returns (true) on any CAS
+         * or consistency check failure so caller can retry.
+         *
+         * @return false if no progress can be made, else true
+         */
+        final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
+            boolean stat = true, removed = false, empty = true;
+            ForkJoinTask<?>[] a; int m, s, b, n;
+            if ((a = array) != null && (m = a.length - 1) >= 0 &&
+                (n = (s = top) - (b = base)) > 0) {
+                for (ForkJoinTask<?> t;;) {           // traverse from s to b
+                    int j = ((--s & m) << ASHIFT) + ABASE;
+                    t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
+                    if (t == null)                    // inconsistent length
+                        break;
+                    else if (t == task) {
+                        if (s + 1 == top) {           // pop
+                            if (!U.compareAndSwapObject(a, j, task, null))
+                                break;
+                            top = s;
+                            removed = true;
+                        }
+                        else if (base == b)           // replace with proxy
+                            removed = U.compareAndSwapObject(a, j, task,
+                                                             new EmptyTask());
+                        break;
+                    }
+                    else if (t.status >= 0)
+                        empty = false;
+                    else if (s + 1 == top) {          // pop and throw away
+                        if (U.compareAndSwapObject(a, j, t, null))
+                            top = s;
+                        break;
+                    }
+                    if (--n == 0) {
+                        if (!empty && base == b)
+                            stat = false;
+                        break;
+                    }
+                }
+            }
+            if (removed)
+                task.doExec();
+            return stat;
+        }
+
+        /**
+         * Polls for and executes the given task or any other task in
+         * its CountedCompleter computation.
+         */
+        final boolean pollAndExecCC(ForkJoinTask<?> root) {
+            ForkJoinTask<?>[] a; int b; Object o;
+            outer: while ((b = base) - top < 0 && (a = array) != null) {
+                long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                if ((o = U.getObject(a, j)) == null ||
+                    !(o instanceof CountedCompleter))
+                    break;
+                for (CountedCompleter<?> t = (CountedCompleter<?>)o, r = t;;) {
+                    if (r == root) {
+                        if (base == b &&
+                            U.compareAndSwapObject(a, j, t, null)) {
+                            base = b + 1;
+                            t.doExec();
+                            return true;
+                        }
+                        else
+                            break; // restart
+                    }
+                    if ((r = r.completer) == null)
+                        break outer; // not part of root computation
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Executes a top-level task and any local tasks remaining
+         * after execution.
+         */
+        final void runTask(ForkJoinTask<?> t) {
+            if (t != null) {
+                (currentSteal = t).doExec();
+                currentSteal = null;
+                ++nsteals;
+                if (base - top < 0) {       // process remaining local tasks
+                    if (mode == 0)
+                        popAndExecAll();
+                    else
+                        pollAndExecAll();
+                }
+            }
+        }
+
+        /**
+         * Executes a non-top-level (stolen) task.
+         */
+        final void runSubtask(ForkJoinTask<?> t) {
+            if (t != null) {
+                ForkJoinTask<?> ps = currentSteal;
+                (currentSteal = t).doExec();
+                currentSteal = ps;
+            }
+        }
+
+        /**
+         * Returns true if owned and not known to be blocked.
+         */
+        final boolean isApparentlyUnblocked() {
+            Thread wt; Thread.State s;
+            return (eventCount >= 0 &&
+                    (wt = owner) != null &&
+                    (s = wt.getState()) != Thread.State.BLOCKED &&
+                    s != Thread.State.WAITING &&
+                    s != Thread.State.TIMED_WAITING);
+        }
+
+        // Unsafe mechanics
+        private static final sun.misc.Unsafe U;
+        private static final long QLOCK;
+        private static final int ABASE;
+        private static final int ASHIFT;
+        static {
+            try {
+                U = sun.misc.Unsafe.getUnsafe();
+                Class<?> k = WorkQueue.class;
+                Class<?> ak = ForkJoinTask[].class;
+                QLOCK = U.objectFieldOffset
+                    (k.getDeclaredField("qlock"));
+                ABASE = U.arrayBaseOffset(ak);
+                int scale = U.arrayIndexScale(ak);
+                if ((scale & (scale - 1)) != 0)
+                    throw new Error("data type scale not a power of two");
+                ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+            } catch (Exception e) {
+                throw new Error(e);
+            }
+        }
+    }
+
+    // static fields (initialized in static initializer below)
+
+    /**
      * Creates a new ForkJoinWorkerThread. This factory is used unless
      * overridden in ForkJoinPool constructors.
      */
@@ -374,107 +1054,93 @@
         defaultForkJoinWorkerThreadFactory;
 
     /**
+     * Per-thread submission bookkeeping. Shared across all pools
+     * to reduce ThreadLocal pollution and because random motion
+     * to avoid contention in one pool is likely to hold for others.
+     * Lazily initialized on first submission (but null-checked
+     * in other contexts to avoid unnecessary initialization).
+     */
+    static final ThreadLocal<Submitter> submitters;
+
+    /**
      * Permission required for callers of methods that may start or
      * kill threads.
      */
     private static final RuntimePermission modifyThreadPermission;
 
     /**
-     * If there is a security manager, makes sure caller has
-     * permission to modify threads.
+     * Common (static) pool. Non-null for public use unless a static
+     * construction exception, but internal usages null-check on use
+     * to paranoically avoid potential initialization circularities
+     * as well as to simplify generated code.
      */
-    private static void checkPermission() {
-        SecurityManager security = System.getSecurityManager();
-        if (security != null)
-            security.checkPermission(modifyThreadPermission);
+    static final ForkJoinPool commonPool;
+
+    /**
+     * Common pool parallelism. Must equal commonPool.parallelism.
+     */
+    static final int commonPoolParallelism;
+
+    /**
+     * Sequence number for creating workerNamePrefix.
+     */
+    private static int poolNumberSequence;
+
+    /**
+     * Returns the next sequence number. We don't expect this to
+     * ever contend, so use simple builtin sync.
+     */
+    private static final synchronized int nextPoolId() {
+        return ++poolNumberSequence;
     }
 
-    /**
-     * Generator for assigning sequence numbers as pool names.
-     */
-    private static final AtomicInteger poolNumberGenerator;
+    // static constants
 
     /**
-     * Generator for initial random seeds for worker victim
-     * selection. This is used only to create initial seeds. Random
-     * steals use a cheaper xorshift generator per steal attempt. We
-     * don't expect much contention on seedGenerator, so just use a
-     * plain Random.
+     * Initial timeout value (in nanoseconds) for the thread
+     * triggering quiescence to park waiting for new work. On timeout,
+     * the thread will instead try to shrink the number of
+     * workers. The value should be large enough to avoid overly
+     * aggressive shrinkage during most transient stalls (long GCs
+     * etc).
      */
-    static final Random workerSeedGenerator;
+    private static final long IDLE_TIMEOUT      = 2000L * 1000L * 1000L; // 2sec
 
     /**
-     * Array holding all worker threads in the pool.  Initialized upon
-     * construction. Array size must be a power of two.  Updates and
-     * replacements are protected by scanGuard, but the array is
-     * always kept in a consistent enough state to be randomly
-     * accessed without locking by workers performing work-stealing,
-     * as well as other traversal-based methods in this class, so long
-     * as reads memory-acquire by first reading ctl. All readers must
-     * tolerate that some array slots may be null.
+     * Timeout value when there are more threads than parallelism level
      */
-    ForkJoinWorkerThread[] workers;
+    private static final long FAST_IDLE_TIMEOUT =  200L * 1000L * 1000L;
 
     /**
-     * Initial size for submission queue array. Must be a power of
-     * two.  In many applications, these always stay small so we use a
-     * small initial cap.
+     * Tolerance for idle timeouts, to cope with timer undershoots
      */
-    private static final int INITIAL_QUEUE_CAPACITY = 8;
+    private static final long TIMEOUT_SLOP = 2000000L; // 20ms
 
     /**
-     * Maximum size for submission queue array. Must be a power of two
-     * less than or equal to 1 << (31 - width of array entry) to
-     * ensure lack of index wraparound, but is capped at a lower
-     * value to help users trap runaway computations.
+     * The maximum stolen->joining link depth allowed in method
+     * tryHelpStealer.  Must be a power of two.  Depths for legitimate
+     * chains are unbounded, but we use a fixed constant to avoid
+     * (otherwise unchecked) cycles and to bound staleness of
+     * traversal parameters at the expense of sometimes blocking when
+     * we could be helping.
      */
-    private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 24; // 16M
+    private static final int MAX_HELP = 64;
 
     /**
-     * Array serving as submission queue. Initialized upon construction.
+     * Increment for seed generators. See class ThreadLocal for
+     * explanation.
      */
-    private ForkJoinTask<?>[] submissionQueue;
+    private static final int SEED_INCREMENT = 0x61c88647;
 
-    /**
-     * Lock protecting submissions array for addSubmission
-     */
-    private final ReentrantLock submissionLock;
-
-    /**
-     * Condition for awaitTermination, using submissionLock for
-     * convenience.
-     */
-    private final Condition termination;
-
-    /**
-     * Creation factory for worker threads.
-     */
-    private final ForkJoinWorkerThreadFactory factory;
-
-    /**
-     * The uncaught exception handler used when any worker abruptly
-     * terminates.
-     */
-    final Thread.UncaughtExceptionHandler ueh;
-
-    /**
-     * Prefix for assigning names to worker threads
-     */
-    private final String workerNamePrefix;
-
-    /**
-     * Sum of per-thread steal counts, updated only when threads are
-     * idle or terminating.
-     */
-    private volatile long stealCount;
-
-    /**
-     * Main pool control -- a long packed with:
+    /*
+     * Bits and masks for control variables
+     *
+     * Field ctl is a long packed with:
      * AC: Number of active running workers minus target parallelism (16 bits)
      * TC: Number of total workers minus target parallelism (16 bits)
      * ST: true if pool is terminating (1 bit)
      * EC: the wait count of top waiting thread (15 bits)
-     * ID: ~poolIndex of top of Treiber stack of waiting threads (16 bits)
+     * ID: poolIndex of top of Treiber stack of waiters (16 bits)
      *
      * When convenient, we can extract the upper 32 bits of counts and
      * the lower 32 bits of queue state, u = (int)(ctl >>> 32) and e =
@@ -483,13 +1149,26 @@
      * parallelism and the positionings of fields makes it possible to
      * perform the most common checks via sign tests of fields: When
      * ac is negative, there are not enough active workers, when tc is
-     * negative, there are not enough total workers, when id is
-     * negative, there is at least one waiting worker, and when e is
+     * negative, there are not enough total workers, and when e is
      * negative, the pool is terminating.  To deal with these possibly
      * negative fields, we use casts in and out of "short" and/or
      * signed shifts to maintain signedness.
+     *
+     * When a thread is queued (inactivated), its eventCount field is
+     * set negative, which is the only way to tell if a worker is
+     * prevented from executing tasks, even though it must continue to
+     * scan for them to avoid queuing races. Note however that
+     * eventCount updates lag releases so usage requires care.
+     *
+     * Field plock is an int packed with:
+     * SHUTDOWN: true if shutdown is enabled (1 bit)
+     * SEQ:  a sequence lock, with PL_LOCK bit set if locked (30 bits)
+     * SIGNAL: set when threads may be waiting on the lock (1 bit)
+     *
+     * The sequence number enables simple consistency checks:
+     * Staleness of read-only operations on the workQueues array can
+     * be checked by comparing plock before vs after the reads.
      */
-    volatile long ctl;
 
     // bit positions/shifts for fields
     private static final int  AC_SHIFT   = 48;
@@ -498,8 +1177,10 @@
     private static final int  EC_SHIFT   = 16;
 
     // bounds
-    private static final int  MAX_ID     = 0x7fff;  // max poolIndex
-    private static final int  SMASK      = 0xffff;  // mask short bits
+    private static final int  SMASK      = 0xffff;  // short bits
+    private static final int  MAX_CAP    = 0x7fff;  // max #workers - 1
+    private static final int  EVENMASK   = 0xfffe;  // even short bits
+    private static final int  SQMASK     = 0x007e;  // max 64 (even) slots
     private static final int  SHORT_SIGN = 1 << 15;
     private static final int  INT_SIGN   = 1 << 31;
 
@@ -521,648 +1202,648 @@
     private static final int  UTC_UNIT   = 1 << UTC_SHIFT;
 
     // masks and units for dealing with e = (int)ctl
-    private static final int  E_MASK     = 0x7fffffff; // no STOP_BIT
-    private static final int  EC_UNIT    = 1 << EC_SHIFT;
+    private static final int E_MASK      = 0x7fffffff; // no STOP_BIT
+    private static final int E_SEQ       = 1 << EC_SHIFT;
+
+    // plock bits
+    private static final int SHUTDOWN    = 1 << 31;
+    private static final int PL_LOCK     = 2;
+    private static final int PL_SIGNAL   = 1;
+    private static final int PL_SPINS    = 1 << 8;
+
+    // access mode for WorkQueue
+    static final int LIFO_QUEUE          =  0;
+    static final int FIFO_QUEUE          =  1;
+    static final int SHARED_QUEUE        = -1;
+
+    // bounds for #steps in scan loop -- must be power 2 minus 1
+    private static final int MIN_SCAN    = 0x1ff;   // cover estimation slop
+    private static final int MAX_SCAN    = 0x1ffff; // 4 * max workers
+
+    // Instance fields
+
+    /*
+     * Field layout of this class tends to matter more than one would
+     * like. Runtime layout order is only loosely related to
+     * declaration order and may differ across JVMs, but the following
+     * empirically works OK on current JVMs.
+     */
+
+    // Heuristic padding to ameliorate unfortunate memory placements
+    volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06;
+
+    volatile long stealCount;                  // collects worker counts
+    volatile long ctl;                         // main pool control
+    volatile int plock;                        // shutdown status and seqLock
+    volatile int indexSeed;                    // worker/submitter index seed
+    final int config;                          // mode and parallelism level
+    WorkQueue[] workQueues;                    // main registry
+    final ForkJoinWorkerThreadFactory factory;
+    final Thread.UncaughtExceptionHandler ueh; // per-worker UEH
+    final String workerNamePrefix;             // to create worker name string
+
+    volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17;
+    volatile Object pad18, pad19, pad1a, pad1b;
 
     /**
-     * The target parallelism level.
+     * Acquires the plock lock to protect worker array and related
+     * updates. This method is called only if an initial CAS on plock
+     * fails. This acts as a spinlock for normal cases, but falls back
+     * to builtin monitor to block when (rarely) needed. This would be
+     * a terrible idea for a highly contended lock, but works fine as
+     * a more conservative alternative to a pure spinlock.
      */
-    final int parallelism;
-
-    /**
-     * Index (mod submission queue length) of next element to take
-     * from submission queue. Usage is identical to that for
-     * per-worker queues -- see ForkJoinWorkerThread internal
-     * documentation.
-     */
-    volatile int queueBase;
-
-    /**
-     * Index (mod submission queue length) of next element to add
-     * in submission queue. Usage is identical to that for
-     * per-worker queues -- see ForkJoinWorkerThread internal
-     * documentation.
-     */
-    int queueTop;
-
-    /**
-     * True when shutdown() has been called.
-     */
-    volatile boolean shutdown;
-
-    /**
-     * True if use local fifo, not default lifo, for local polling.
-     * Read by, and replicated by ForkJoinWorkerThreads.
-     */
-    final boolean locallyFifo;
-
-    /**
-     * The number of threads in ForkJoinWorkerThreads.helpQuiescePool.
-     * When non-zero, suppresses automatic shutdown when active
-     * counts become zero.
-     */
-    volatile int quiescerCount;
-
-    /**
-     * The number of threads blocked in join.
-     */
-    volatile int blockedCount;
-
-    /**
-     * Counter for worker Thread names (unrelated to their poolIndex)
-     */
-    private volatile int nextWorkerNumber;
-
-    /**
-     * The index for the next created worker. Accessed under scanGuard.
-     */
-    private int nextWorkerIndex;
-
-    /**
-     * SeqLock and index masking for updates to workers array.  Locked
-     * when SG_UNIT is set. Unlocking clears bit by adding
-     * SG_UNIT. Staleness of read-only operations can be checked by
-     * comparing scanGuard to value before the reads. The low 16 bits
-     * (i.e, anding with SMASK) hold (the smallest power of two
-     * covering all worker indices, minus one, and is used to avoid
-     * dealing with large numbers of null slots when the workers array
-     * is overallocated.
-     */
-    volatile int scanGuard;
-
-    private static final int SG_UNIT = 1 << 16;
-
-    /**
-     * The wakeup interval (in nanoseconds) for a worker waiting for a
-     * task when the pool is quiescent to instead try to shrink the
-     * number of workers.  The exact value does not matter too
-     * much. It must be short enough to release resources during
-     * sustained periods of idleness, but not so short that threads
-     * are continually re-created.
-     */
-    private static final long SHRINK_RATE =
-        4L * 1000L * 1000L * 1000L; // 4 seconds
-
-    /**
-     * Top-level loop for worker threads: On each step: if the
-     * previous step swept through all queues and found no tasks, or
-     * there are excess threads, then possibly blocks. Otherwise,
-     * scans for and, if found, executes a task. Returns when pool
-     * and/or worker terminate.
-     *
-     * @param w the worker
-     */
-    final void work(ForkJoinWorkerThread w) {
-        boolean swept = false;                // true on empty scans
-        long c;
-        while (!w.terminate && (int)(c = ctl) >= 0) {
-            int a;                            // active count
-            if (!swept && (a = (int)(c >> AC_SHIFT)) <= 0)
-                swept = scan(w, a);
-            else if (tryAwaitWork(w, c))
-                swept = false;
+    private int acquirePlock() {
+        int spins = PL_SPINS, r = 0, ps, nps;
+        for (;;) {
+            if (((ps = plock) & PL_LOCK) == 0 &&
+                U.compareAndSwapInt(this, PLOCK, ps, nps = ps + PL_LOCK))
+                return nps;
+            else if (r == 0) { // randomize spins if possible
+                Thread t = Thread.currentThread(); WorkQueue w; Submitter z;
+                if ((t instanceof ForkJoinWorkerThread) &&
+                    (w = ((ForkJoinWorkerThread)t).workQueue) != null)
+                    r = w.seed;
+                else if ((z = submitters.get()) != null)
+                    r = z.seed;
+                else
+                    r = 1;
+            }
+            else if (spins >= 0) {
+                r ^= r << 1; r ^= r >>> 3; r ^= r << 10; // xorshift
+                if (r >= 0)
+                    --spins;
+            }
+            else if (U.compareAndSwapInt(this, PLOCK, ps, ps | PL_SIGNAL)) {
+                synchronized (this) {
+                    if ((plock & PL_SIGNAL) != 0) {
+                        try {
+                            wait();
+                        } catch (InterruptedException ie) {
+                            try {
+                                Thread.currentThread().interrupt();
+                            } catch (SecurityException ignore) {
+                            }
+                        }
+                    }
+                    else
+                        notifyAll();
+                }
+            }
         }
     }
 
-    // Signalling
+    /**
+     * Unlocks and signals any thread waiting for plock. Called only
+     * when CAS of seq value for unlock fails.
+     */
+    private void releasePlock(int ps) {
+        plock = ps;
+        synchronized (this) { notifyAll(); }
+    }
 
     /**
-     * Wakes up or creates a worker.
+     * Performs secondary initialization, called when plock is zero.
+     * Creates workQueue array and sets plock to a valid value.  The
+     * lock body must be exception-free (so no try/finally) so we
+     * optimistically allocate new array outside the lock and throw
+     * away if (very rarely) not needed. (A similar tactic is used in
+     * fullExternalPush.)  Because the plock seq value can eventually
+     * wrap around zero, this method harmlessly fails to reinitialize
+     * if workQueues exists, while still advancing plock.
+     *
+     * Additionally tries to create the first worker.
      */
-    final void signalWork() {
-        /*
-         * The while condition is true if: (there is are too few total
-         * workers OR there is at least one waiter) AND (there are too
-         * few active workers OR the pool is terminating).  The value
-         * of e distinguishes the remaining cases: zero (no waiters)
-         * for create, negative if terminating (in which case do
-         * nothing), else release a waiter. The secondary checks for
-         * release (non-null array etc) can fail if the pool begins
-         * terminating after the test, and don't impose any added cost
-         * because JVMs must perform null and bounds checks anyway.
-         */
-        long c; int e, u;
-        while ((((e = (int)(c = ctl)) | (u = (int)(c >>> 32))) &
-                (INT_SIGN|SHORT_SIGN)) == (INT_SIGN|SHORT_SIGN) && e >= 0) {
-            if (e > 0) {                         // release a waiting worker
-                int i; ForkJoinWorkerThread w; ForkJoinWorkerThread[] ws;
-                if ((ws = workers) == null ||
-                    (i = ~e & SMASK) >= ws.length ||
-                    (w = ws[i]) == null)
-                    break;
-                long nc = (((long)(w.nextWait & E_MASK)) |
-                           ((long)(u + UAC_UNIT) << 32));
-                if (w.eventCount == e &&
-                    UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
-                    w.eventCount = (e + EC_UNIT) & E_MASK;
-                    if (w.parked)
-                        UNSAFE.unpark(w);
-                    break;
+    private void initWorkers() {
+        WorkQueue[] ws, nws; int ps;
+        int p = config & SMASK;        // find power of two table size
+        int n = (p > 1) ? p - 1 : 1;   // ensure at least 2 slots
+        n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
+        n = (n + 1) << 1;
+        if ((ws = workQueues) == null || ws.length == 0)
+            nws = new WorkQueue[n];
+        else
+            nws = null;
+        if (((ps = plock) & PL_LOCK) != 0 ||
+            !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+            ps = acquirePlock();
+        if (((ws = workQueues) == null || ws.length == 0) && nws != null)
+            workQueues = nws;
+        int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+        if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+            releasePlock(nps);
+        tryAddWorker();
+    }
+
+    /**
+     * Tries to create and start one worker if fewer than target
+     * parallelism level exist. Adjusts counts etc on failure.
+     */
+    private void tryAddWorker() {
+        long c; int u;
+        while ((u = (int)((c = ctl) >>> 32)) < 0 &&
+               (u & SHORT_SIGN) != 0 && (int)c == 0) {
+            long nc = (long)(((u + UTC_UNIT) & UTC_MASK) |
+                             ((u + UAC_UNIT) & UAC_MASK)) << 32;
+            if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                ForkJoinWorkerThreadFactory fac;
+                Throwable ex = null;
+                ForkJoinWorkerThread wt = null;
+                try {
+                    if ((fac = factory) != null &&
+                        (wt = fac.newThread(this)) != null) {
+                        wt.start();
+                        break;
+                    }
+                } catch (Throwable e) {
+                    ex = e;
                 }
-            }
-            else if (UNSAFE.compareAndSwapLong
-                     (this, ctlOffset, c,
-                      (long)(((u + UTC_UNIT) & UTC_MASK) |
-                             ((u + UAC_UNIT) & UAC_MASK)) << 32)) {
-                addWorker();
+                deregisterWorker(wt, ex);
                 break;
             }
         }
     }
 
-    /**
-     * Variant of signalWork to help release waiters on rescans.
-     * Tries once to release a waiter if active count < 0.
-     *
-     * @return false if failed due to contention, else true
-     */
-    private boolean tryReleaseWaiter() {
-        long c; int e, i; ForkJoinWorkerThread w; ForkJoinWorkerThread[] ws;
-        if ((e = (int)(c = ctl)) > 0 &&
-            (int)(c >> AC_SHIFT) < 0 &&
-            (ws = workers) != null &&
-            (i = ~e & SMASK) < ws.length &&
-            (w = ws[i]) != null) {
-            long nc = ((long)(w.nextWait & E_MASK) |
-                       ((c + AC_UNIT) & (AC_MASK|TC_MASK)));
-            if (w.eventCount != e ||
-                !UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc))
-                return false;
-            w.eventCount = (e + EC_UNIT) & E_MASK;
-            if (w.parked)
-                UNSAFE.unpark(w);
-        }
-        return true;
-    }
-
-    // Scanning for tasks
+    //  Registering and deregistering workers
 
     /**
-     * Scans for and, if found, executes one task. Scans start at a
-     * random index of workers array, and randomly select the first
-     * (2*#workers)-1 probes, and then, if all empty, resort to 2
-     * circular sweeps, which is necessary to check quiescence. and
-     * taking a submission only if no stealable tasks were found.  The
-     * steal code inside the loop is a specialized form of
-     * ForkJoinWorkerThread.deqTask, followed bookkeeping to support
-     * helpJoinTask and signal propagation. The code for submission
-     * queues is almost identical. On each steal, the worker completes
-     * not only the task, but also all local tasks that this task may
-     * have generated. On detecting staleness or contention when
-     * trying to take a task, this method returns without finishing
-     * sweep, which allows global state rechecks before retry.
+     * Callback from ForkJoinWorkerThread to establish and record its
+     * WorkQueue. To avoid scanning bias due to packing entries in
+     * front of the workQueues array, we treat the array as a simple
+     * power-of-two hash table using per-thread seed as hash,
+     * expanding as needed.
      *
-     * @param w the worker
-     * @param a the number of active workers
-     * @return true if swept all queues without finding a task
+     * @param wt the worker thread
+     * @return the worker's queue
      */
-    private boolean scan(ForkJoinWorkerThread w, int a) {
-        int g = scanGuard; // mask 0 avoids useless scans if only one active
-        int m = (parallelism == 1 - a && blockedCount == 0) ? 0 : g & SMASK;
-        ForkJoinWorkerThread[] ws = workers;
-        if (ws == null || ws.length <= m)         // staleness check
-            return false;
-        for (int r = w.seed, k = r, j = -(m + m); j <= m + m; ++j) {
-            ForkJoinTask<?> t; ForkJoinTask<?>[] q; int b, i;
-            ForkJoinWorkerThread v = ws[k & m];
-            if (v != null && (b = v.queueBase) != v.queueTop &&
-                (q = v.queue) != null && (i = (q.length - 1) & b) >= 0) {
-                long u = (i << ASHIFT) + ABASE;
-                if ((t = q[i]) != null && v.queueBase == b &&
-                    UNSAFE.compareAndSwapObject(q, u, t, null)) {
-                    int d = (v.queueBase = b + 1) - v.queueTop;
-                    v.stealHint = w.poolIndex;
-                    if (d != 0)
-                        signalWork();             // propagate if nonempty
-                    w.execTask(t);
-                }
-                r ^= r << 13; r ^= r >>> 17; w.seed = r ^ (r << 5);
-                return false;                     // store next seed
-            }
-            else if (j < 0) {                     // xorshift
-                r ^= r << 13; r ^= r >>> 17; k = r ^= r << 5;
-            }
-            else
-                ++k;
-        }
-        if (scanGuard != g)                       // staleness check
-            return false;
-        else {                                    // try to take submission
-            ForkJoinTask<?> t; ForkJoinTask<?>[] q; int b, i;
-            if ((b = queueBase) != queueTop &&
-                (q = submissionQueue) != null &&
-                (i = (q.length - 1) & b) >= 0) {
-                long u = (i << ASHIFT) + ABASE;
-                if ((t = q[i]) != null && queueBase == b &&
-                    UNSAFE.compareAndSwapObject(q, u, t, null)) {
-                    queueBase = b + 1;
-                    w.execTask(t);
-                }
-                return false;
-            }
-            return true;                         // all queues empty
-        }
-    }
-
-    /**
-     * Tries to enqueue worker w in wait queue and await change in
-     * worker's eventCount.  If the pool is quiescent and there is
-     * more than one worker, possibly terminates worker upon exit.
-     * Otherwise, before blocking, rescans queues to avoid missed
-     * signals.  Upon finding work, releases at least one worker
-     * (which may be the current worker). Rescans restart upon
-     * detected staleness or failure to release due to
-     * contention. Note the unusual conventions about Thread.interrupt
-     * here and elsewhere: Because interrupts are used solely to alert
-     * threads to check termination, which is checked here anyway, we
-     * clear status (using Thread.interrupted) before any call to
-     * park, so that park does not immediately return due to status
-     * being set via some other unrelated call to interrupt in user
-     * code.
-     *
-     * @param w the calling worker
-     * @param c the ctl value on entry
-     * @return true if waited or another thread was released upon enq
-     */
-    private boolean tryAwaitWork(ForkJoinWorkerThread w, long c) {
-        int v = w.eventCount;
-        w.nextWait = (int)c;                      // w's successor record
-        long nc = (long)(v & E_MASK) | ((c - AC_UNIT) & (AC_MASK|TC_MASK));
-        if (ctl != c || !UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
-            long d = ctl; // return true if lost to a deq, to force scan
-            return (int)d != (int)c && (d & AC_MASK) >= (c & AC_MASK);
-        }
-        for (int sc = w.stealCount; sc != 0;) {   // accumulate stealCount
-            long s = stealCount;
-            if (UNSAFE.compareAndSwapLong(this, stealCountOffset, s, s + sc))
-                sc = w.stealCount = 0;
-            else if (w.eventCount != v)
-                return true;                      // update next time
-        }
-        if ((!shutdown || !tryTerminate(false)) &&
-            (int)c != 0 && parallelism + (int)(nc >> AC_SHIFT) == 0 &&
-            blockedCount == 0 && quiescerCount == 0)
-            idleAwaitWork(w, nc, c, v);           // quiescent
-        for (boolean rescanned = false;;) {
-            if (w.eventCount != v)
-                return true;
-            if (!rescanned) {
-                int g = scanGuard, m = g & SMASK;
-                ForkJoinWorkerThread[] ws = workers;
-                if (ws != null && m < ws.length) {
-                    rescanned = true;
-                    for (int i = 0; i <= m; ++i) {
-                        ForkJoinWorkerThread u = ws[i];
-                        if (u != null) {
-                            if (u.queueBase != u.queueTop &&
-                                !tryReleaseWaiter())
-                                rescanned = false; // contended
-                            if (w.eventCount != v)
-                                return true;
+    final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
+        Thread.UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps;
+        wt.setDaemon(true);
+        if ((handler = ueh) != null)
+            wt.setUncaughtExceptionHandler(handler);
+        do {} while (!U.compareAndSwapInt(this, INDEXSEED, s = indexSeed,
+                                          s += SEED_INCREMENT) ||
+                     s == 0); // skip 0
+        WorkQueue w = new WorkQueue(this, wt, config >>> 16, s);
+        if (((ps = plock) & PL_LOCK) != 0 ||
+            !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+            ps = acquirePlock();
+        int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+        try {
+            if ((ws = workQueues) != null) {    // skip if shutting down
+                int n = ws.length, m = n - 1;
+                int r = (s << 1) | 1;           // use odd-numbered indices
+                if (ws[r &= m] != null) {       // collision
+                    int probes = 0;             // step by approx half size
+                    int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
+                    while (ws[r = (r + step) & m] != null) {
+                        if (++probes >= n) {
+                            workQueues = ws = Arrays.copyOf(ws, n <<= 1);
+                            m = n - 1;
+                            probes = 0;
                         }
                     }
                 }
-                if (scanGuard != g ||              // stale
-                    (queueBase != queueTop && !tryReleaseWaiter()))
-                    rescanned = false;
-                if (!rescanned)
-                    Thread.yield();                // reduce contention
-                else
-                    Thread.interrupted();          // clear before park
+                w.eventCount = w.poolIndex = r; // volatile write orders
+                ws[r] = w;
             }
-            else {
-                w.parked = true;                   // must recheck
-                if (w.eventCount != v) {
-                    w.parked = false;
-                    return true;
-                }
-                LockSupport.park(this);
-                rescanned = w.parked = false;
-            }
+        } finally {
+            if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+                releasePlock(nps);
         }
+        wt.setName(workerNamePrefix.concat(Integer.toString(w.poolIndex)));
+        return w;
     }
 
     /**
-     * If inactivating worker w has caused pool to become
-     * quiescent, check for pool termination, and wait for event
-     * for up to SHRINK_RATE nanosecs (rescans are unnecessary in
-     * this case because quiescence reflects consensus about lack
-     * of work). On timeout, if ctl has not changed, terminate the
-     * worker. Upon its termination (see deregisterWorker), it may
-     * wake up another worker to possibly repeat this process.
+     * Final callback from terminating worker, as well as upon failure
+     * to construct or start a worker.  Removes record of worker from
+     * array, and adjusts counts. If pool is shutting down, tries to
+     * complete termination.
      *
-     * @param w the calling worker
-     * @param currentCtl the ctl value after enqueuing w
-     * @param prevCtl the ctl value if w terminated
-     * @param v the eventCount w awaits change
+     * @param wt the worker thread or null if construction failed
+     * @param ex the exception causing failure, or null if none
      */
-    private void idleAwaitWork(ForkJoinWorkerThread w, long currentCtl,
-                               long prevCtl, int v) {
-        if (w.eventCount == v) {
-            if (shutdown)
-                tryTerminate(false);
-            ForkJoinTask.helpExpungeStaleExceptions(); // help clean weak refs
-            while (ctl == currentCtl) {
-                long startTime = System.nanoTime();
-                w.parked = true;
-                if (w.eventCount == v)             // must recheck
-                    LockSupport.parkNanos(this, SHRINK_RATE);
-                w.parked = false;
-                if (w.eventCount != v)
-                    break;
-                else if (System.nanoTime() - startTime <
-                         SHRINK_RATE - (SHRINK_RATE / 10)) // timing slop
-                    Thread.interrupted();          // spurious wakeup
-                else if (UNSAFE.compareAndSwapLong(this, ctlOffset,
-                                                   currentCtl, prevCtl)) {
-                    w.terminate = true;            // restore previous
-                    w.eventCount = ((int)currentCtl + EC_UNIT) & E_MASK;
+    final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
+        WorkQueue w = null;
+        if (wt != null && (w = wt.workQueue) != null) {
+            int ps;
+            w.qlock = -1;                // ensure set
+            long ns = w.nsteals, sc;     // collect steal count
+            do {} while (!U.compareAndSwapLong(this, STEALCOUNT,
+                                               sc = stealCount, sc + ns));
+            if (((ps = plock) & PL_LOCK) != 0 ||
+                !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+                ps = acquirePlock();
+            int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+            try {
+                int idx = w.poolIndex;
+                WorkQueue[] ws = workQueues;
+                if (ws != null && idx >= 0 && idx < ws.length && ws[idx] == w)
+                    ws[idx] = null;
+            } finally {
+                if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+                    releasePlock(nps);
+            }
+        }
+
+        long c;                          // adjust ctl counts
+        do {} while (!U.compareAndSwapLong
+                     (this, CTL, c = ctl, (((c - AC_UNIT) & AC_MASK) |
+                                           ((c - TC_UNIT) & TC_MASK) |
+                                           (c & ~(AC_MASK|TC_MASK)))));
+
+        if (!tryTerminate(false, false) && w != null && w.array != null) {
+            w.cancelAll();               // cancel remaining tasks
+            WorkQueue[] ws; WorkQueue v; Thread p; int u, i, e;
+            while ((u = (int)((c = ctl) >>> 32)) < 0 && (e = (int)c) >= 0) {
+                if (e > 0) {             // activate or create replacement
+                    if ((ws = workQueues) == null ||
+                        (i = e & SMASK) >= ws.length ||
+                        (v = ws[i]) != null)
+                        break;
+                    long nc = (((long)(v.nextWait & E_MASK)) |
+                               ((long)(u + UAC_UNIT) << 32));
+                    if (v.eventCount != (e | INT_SIGN))
+                        break;
+                    if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                        v.eventCount = (e + E_SEQ) & E_MASK;
+                        if ((p = v.parker) != null)
+                            U.unpark(p);
+                        break;
+                    }
+                }
+                else {
+                    if ((short)u < 0)
+                        tryAddWorker();
                     break;
                 }
             }
         }
+        if (ex == null)                     // help clean refs on way out
+            ForkJoinTask.helpExpungeStaleExceptions();
+        else                                // rethrow
+            ForkJoinTask.rethrow(ex);
     }
 
     // Submissions
 
     /**
-     * Enqueues the given task in the submissionQueue.  Same idea as
-     * ForkJoinWorkerThread.pushTask except for use of submissionLock.
+     * Unless shutting down, adds the given task to a submission queue
+     * at submitter's current queue index (modulo submission
+     * range). Only the most common path is directly handled in this
+     * method. All others are relayed to fullExternalPush.
      *
-     * @param t the task
+     * @param task the task. Caller must ensure non-null.
      */
-    private void addSubmission(ForkJoinTask<?> t) {
-        final ReentrantLock lock = this.submissionLock;
-        lock.lock();
-        try {
-            ForkJoinTask<?>[] q; int s, m;
-            if ((q = submissionQueue) != null) {    // ignore if queue removed
-                long u = (((s = queueTop) & (m = q.length-1)) << ASHIFT)+ABASE;
-                UNSAFE.putOrderedObject(q, u, t);
-                queueTop = s + 1;
-                if (s - queueBase == m)
-                    growSubmissionQueue();
+    final void externalPush(ForkJoinTask<?> task) {
+        WorkQueue[] ws; WorkQueue q; Submitter z; int m; ForkJoinTask<?>[] a;
+        if ((z = submitters.get()) != null && plock > 0 &&
+            (ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&
+            (q = ws[m & z.seed & SQMASK]) != null &&
+            U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock
+            int b = q.base, s = q.top, n, an;
+            if ((a = q.array) != null && (an = a.length) > (n = s + 1 - b)) {
+                int j = (((an - 1) & s) << ASHIFT) + ABASE;
+                U.putOrderedObject(a, j, task);
+                q.top = s + 1;                     // push on to deque
+                q.qlock = 0;
+                if (n <= 2)
+                    signalWork(q);
+                return;
             }
-        } finally {
-            lock.unlock();
+            q.qlock = 0;
         }
-        signalWork();
+        fullExternalPush(task);
     }
 
-    //  (pollSubmission is defined below with exported methods)
-
     /**
-     * Creates or doubles submissionQueue array.
-     * Basically identical to ForkJoinWorkerThread version.
+     * Full version of externalPush. This method is called, among
+     * other times, upon the first submission of the first task to the
+     * pool, so must perform secondary initialization (via
+     * initWorkers). It also detects first submission by an external
+     * thread by looking up its ThreadLocal, and creates a new shared
+     * queue if the one at index if empty or contended. The plock lock
+     * body must be exception-free (so no try/finally) so we
+     * optimistically allocate new queues outside the lock and throw
+     * them away if (very rarely) not needed.
      */
-    private void growSubmissionQueue() {
-        ForkJoinTask<?>[] oldQ = submissionQueue;
-        int size = oldQ != null ? oldQ.length << 1 : INITIAL_QUEUE_CAPACITY;
-        if (size > MAXIMUM_QUEUE_CAPACITY)
-            throw new RejectedExecutionException("Queue capacity exceeded");
-        if (size < INITIAL_QUEUE_CAPACITY)
-            size = INITIAL_QUEUE_CAPACITY;
-        ForkJoinTask<?>[] q = submissionQueue = new ForkJoinTask<?>[size];
-        int mask = size - 1;
-        int top = queueTop;
-        int oldMask;
-        if (oldQ != null && (oldMask = oldQ.length - 1) >= 0) {
-            for (int b = queueBase; b != top; ++b) {
-                long u = ((b & oldMask) << ASHIFT) + ABASE;
-                Object x = UNSAFE.getObjectVolatile(oldQ, u);
-                if (x != null && UNSAFE.compareAndSwapObject(oldQ, u, x, null))
-                    UNSAFE.putObjectVolatile
-                        (q, ((b & mask) << ASHIFT) + ABASE, x);
+    private void fullExternalPush(ForkJoinTask<?> task) {
+        int r = 0; // random index seed
+        for (Submitter z = submitters.get();;) {
+            WorkQueue[] ws; WorkQueue q; int ps, m, k;
+            if (z == null) {
+                if (U.compareAndSwapInt(this, INDEXSEED, r = indexSeed,
+                                        r += SEED_INCREMENT) && r != 0)
+                    submitters.set(z = new Submitter(r));
             }
-        }
-    }
-
-    // Blocking support
-
-    /**
-     * Tries to increment blockedCount, decrement active count
-     * (sometimes implicitly) and possibly release or create a
-     * compensating worker in preparation for blocking. Fails
-     * on contention or termination.
-     *
-     * @return true if the caller can block, else should recheck and retry
-     */
-    private boolean tryPreBlock() {
-        int b = blockedCount;
-        if (UNSAFE.compareAndSwapInt(this, blockedCountOffset, b, b + 1)) {
-            int pc = parallelism;
-            do {
-                ForkJoinWorkerThread[] ws; ForkJoinWorkerThread w;
-                int e, ac, tc, i;
-                long c = ctl;
-                int u = (int)(c >>> 32);
-                if ((e = (int)c) < 0) {
-                                                 // skip -- terminating
-                }
-                else if ((ac = (u >> UAC_SHIFT)) <= 0 && e != 0 &&
-                         (ws = workers) != null &&
-                         (i = ~e & SMASK) < ws.length &&
-                         (w = ws[i]) != null) {
-                    long nc = ((long)(w.nextWait & E_MASK) |
-                               (c & (AC_MASK|TC_MASK)));
-                    if (w.eventCount == e &&
-                        UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
-                        w.eventCount = (e + EC_UNIT) & E_MASK;
-                        if (w.parked)
-                            UNSAFE.unpark(w);
-                        return true;             // release an idle worker
-                    }
-                }
-                else if ((tc = (short)(u >>> UTC_SHIFT)) >= 0 && ac + pc > 1) {
-                    long nc = ((c - AC_UNIT) & AC_MASK) | (c & ~AC_MASK);
-                    if (UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc))
-                        return true;             // no compensation needed
-                }
-                else if (tc + pc < MAX_ID) {
-                    long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK);
-                    if (UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
-                        addWorker();
-                        return true;            // create a replacement
-                    }
-                }
-                // try to back out on any failure and let caller retry
-            } while (!UNSAFE.compareAndSwapInt(this, blockedCountOffset,
-                                               b = blockedCount, b - 1));
-        }
-        return false;
-    }
-
-    /**
-     * Decrements blockedCount and increments active count.
-     */
-    private void postBlock() {
-        long c;
-        do {} while (!UNSAFE.compareAndSwapLong(this, ctlOffset,  // no mask
-                                                c = ctl, c + AC_UNIT));
-        int b;
-        do {} while (!UNSAFE.compareAndSwapInt(this, blockedCountOffset,
-                                               b = blockedCount, b - 1));
-    }
-
-    /**
-     * Possibly blocks waiting for the given task to complete, or
-     * cancels the task if terminating.  Fails to wait if contended.
-     *
-     * @param joinMe the task
-     */
-    final void tryAwaitJoin(ForkJoinTask<?> joinMe) {
-        Thread.interrupted(); // clear interrupts before checking termination
-        if (joinMe.status >= 0) {
-            if (tryPreBlock()) {
-                joinMe.tryAwaitDone(0L);
-                postBlock();
+            else if (r == 0) {               // move to a different index
+                r = z.seed;
+                r ^= r << 13;                // same xorshift as WorkQueues
+                r ^= r >>> 17;
+                z.seed = r ^ (r << 5);
             }
-            else if ((ctl & STOP_BIT) != 0L)
-                joinMe.cancelIgnoringExceptions();
-        }
-    }
-
-    /**
-     * Possibly blocks the given worker waiting for joinMe to
-     * complete or timeout.
-     *
-     * @param joinMe the task
-     * @param nanos the wait time for underlying Object.wait
-     */
-    final void timedAwaitJoin(ForkJoinTask<?> joinMe, long nanos) {
-        while (joinMe.status >= 0) {
-            Thread.interrupted();
-            if ((ctl & STOP_BIT) != 0L) {
-                joinMe.cancelIgnoringExceptions();
-                break;
-            }
-            if (tryPreBlock()) {
-                long last = System.nanoTime();
-                while (joinMe.status >= 0) {
-                    long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
-                    if (millis <= 0)
-                        break;
-                    joinMe.tryAwaitDone(millis);
-                    if (joinMe.status < 0)
-                        break;
-                    if ((ctl & STOP_BIT) != 0L) {
-                        joinMe.cancelIgnoringExceptions();
-                        break;
-                    }
-                    long now = System.nanoTime();
-                    nanos -= now - last;
-                    last = now;
-                }
-                postBlock();
-                break;
-            }
-        }
-    }
-
-    /**
-     * If necessary, compensates for blocker, and blocks.
-     */
-    private void awaitBlocker(ManagedBlocker blocker)
-        throws InterruptedException {
-        while (!blocker.isReleasable()) {
-            if (tryPreBlock()) {
-                try {
-                    do {} while (!blocker.isReleasable() && !blocker.block());
-                } finally {
-                    postBlock();
-                }
-                break;
-            }
-        }
-    }
-
-    // Creating, registering and deregistring workers
-
-    /**
-     * Tries to create and start a worker; minimally rolls back counts
-     * on failure.
-     */
-    private void addWorker() {
-        Throwable ex = null;
-        ForkJoinWorkerThread t = null;
-        try {
-            t = factory.newThread(this);
-        } catch (Throwable e) {
-            ex = e;
-        }
-        if (t == null) {  // null or exceptional factory return
-            long c;       // adjust counts
-            do {} while (!UNSAFE.compareAndSwapLong
-                         (this, ctlOffset, c = ctl,
-                          (((c - AC_UNIT) & AC_MASK) |
-                           ((c - TC_UNIT) & TC_MASK) |
-                           (c & ~(AC_MASK|TC_MASK)))));
-            // Propagate exception if originating from an external caller
-            if (!tryTerminate(false) && ex != null &&
-                !(Thread.currentThread() instanceof ForkJoinWorkerThread))
-                SneakyThrow.sneakyThrow(ex); // android-changed
-        }
-        else
-            t.start();
-    }
-
-    /**
-     * Callback from ForkJoinWorkerThread constructor to assign a
-     * public name
-     */
-    final String nextWorkerName() {
-        for (int n;;) {
-            if (UNSAFE.compareAndSwapInt(this, nextWorkerNumberOffset,
-                                         n = nextWorkerNumber, ++n))
-                return workerNamePrefix + n;
-        }
-    }
-
-    /**
-     * Callback from ForkJoinWorkerThread constructor to
-     * determine its poolIndex and record in workers array.
-     *
-     * @param w the worker
-     * @return the worker's pool index
-     */
-    final int registerWorker(ForkJoinWorkerThread w) {
-        /*
-         * In the typical case, a new worker acquires the lock, uses
-         * next available index and returns quickly.  Since we should
-         * not block callers (ultimately from signalWork or
-         * tryPreBlock) waiting for the lock needed to do this, we
-         * instead help release other workers while waiting for the
-         * lock.
-         */
-        for (int g;;) {
-            ForkJoinWorkerThread[] ws;
-            if (((g = scanGuard) & SG_UNIT) == 0 &&
-                UNSAFE.compareAndSwapInt(this, scanGuardOffset,
-                                         g, g | SG_UNIT)) {
-                int k = nextWorkerIndex;
-                try {
-                    if ((ws = workers) != null) { // ignore on shutdown
-                        int n = ws.length;
-                        if (k < 0 || k >= n || ws[k] != null) {
-                            for (k = 0; k < n && ws[k] != null; ++k)
-                                ;
-                            if (k == n)
-                                ws = workers = Arrays.copyOf(ws, n << 1);
+            else if ((ps = plock) < 0)
+                throw new RejectedExecutionException();
+            else if (ps == 0 || (ws = workQueues) == null ||
+                     (m = ws.length - 1) < 0)
+                initWorkers();
+            else if ((q = ws[k = r & m & SQMASK]) != null) {
+                if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) {
+                    ForkJoinTask<?>[] a = q.array;
+                    int s = q.top;
+                    boolean submitted = false;
+                    try {                      // locked version of push
+                        if ((a != null && a.length > s + 1 - q.base) ||
+                            (a = q.growArray()) != null) {   // must presize
+                            int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
+                            U.putOrderedObject(a, j, task);
+                            q.top = s + 1;
+                            submitted = true;
                         }
-                        ws[k] = w;
-                        nextWorkerIndex = k + 1;
-                        int m = g & SMASK;
-                        g = (k > m) ? ((m << 1) + 1) & SMASK : g + (SG_UNIT<<1);
+                    } finally {
+                        q.qlock = 0;  // unlock
                     }
-                } finally {
-                    scanGuard = g;
+                    if (submitted) {
+                        signalWork(q);
+                        return;
+                    }
                 }
-                return k;
+                r = 0; // move on failure
             }
-            else if ((ws = workers) != null) { // help release others
-                for (ForkJoinWorkerThread u : ws) {
-                    if (u != null && u.queueBase != u.queueTop) {
-                        if (tryReleaseWaiter())
+            else if (((ps = plock) & PL_LOCK) == 0) { // create new queue
+                q = new WorkQueue(this, null, SHARED_QUEUE, r);
+                if (((ps = plock) & PL_LOCK) != 0 ||
+                    !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+                    ps = acquirePlock();
+                if ((ws = workQueues) != null && k < ws.length && ws[k] == null)
+                    ws[k] = q;
+                int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+                if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+                    releasePlock(nps);
+            }
+            else
+                r = 0; // try elsewhere while lock held
+        }
+    }
+
+    // Maintaining ctl counts
+
+    /**
+     * Increments active count; mainly called upon return from blocking.
+     */
+    final void incrementActiveCount() {
+        long c;
+        do {} while (!U.compareAndSwapLong(this, CTL, c = ctl, c + AC_UNIT));
+    }
+
+    /**
+     * Tries to create or activate a worker if too few are active.
+     *
+     * @param q the (non-null) queue holding tasks to be signalled
+     */
+    final void signalWork(WorkQueue q) {
+        int hint = q.poolIndex;
+        long c; int e, u, i, n; WorkQueue[] ws; WorkQueue w; Thread p;
+        while ((u = (int)((c = ctl) >>> 32)) < 0) {
+            if ((e = (int)c) > 0) {
+                if ((ws = workQueues) != null && ws.length > (i = e & SMASK) &&
+                    (w = ws[i]) != null && w.eventCount == (e | INT_SIGN)) {
+                    long nc = (((long)(w.nextWait & E_MASK)) |
+                               ((long)(u + UAC_UNIT) << 32));
+                    if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                        w.hint = hint;
+                        w.eventCount = (e + E_SEQ) & E_MASK;
+                        if ((p = w.parker) != null)
+                            U.unpark(p);
+                        break;
+                    }
+                    if (q.top - q.base <= 0)
+                        break;
+                }
+                else
+                    break;
+            }
+            else {
+                if ((short)u < 0)
+                    tryAddWorker();
+                break;
+            }
+        }
+    }
+
+    // Scanning for tasks
+
+    /**
+     * Top-level runloop for workers, called by ForkJoinWorkerThread.run.
+     */
+    final void runWorker(WorkQueue w) {
+        w.growArray(); // allocate queue
+        do { w.runTask(scan(w)); } while (w.qlock >= 0);
+    }
+
+    /**
+     * Scans for and, if found, returns one task, else possibly
+     * inactivates the worker. This method operates on single reads of
+     * volatile state and is designed to be re-invoked continuously,
+     * in part because it returns upon detecting inconsistencies,
+     * contention, or state changes that indicate possible success on
+     * re-invocation.
+     *
+     * The scan searches for tasks across queues (starting at a random
+     * index, and relying on registerWorker to irregularly scatter
+     * them within array to avoid bias), checking each at least twice.
+     * The scan terminates upon either finding a non-empty queue, or
+     * completing the sweep. If the worker is not inactivated, it
+     * takes and returns a task from this queue. Otherwise, if not
+     * activated, it signals workers (that may include itself) and
+     * returns so caller can retry. Also returns for true if the
+     * worker array may have changed during an empty scan.  On failure
+     * to find a task, we take one of the following actions, after
+     * which the caller will retry calling this method unless
+     * terminated.
+     *
+     * * If pool is terminating, terminate the worker.
+     *
+     * * If not already enqueued, try to inactivate and enqueue the
+     * worker on wait queue. Or, if inactivating has caused the pool
+     * to be quiescent, relay to idleAwaitWork to possibly shrink
+     * pool.
+     *
+     * * If already enqueued and none of the above apply, possibly
+     * park awaiting signal, else lingering to help scan and signal.
+     *
+     * * If a non-empty queue discovered or left as a hint,
+     * help wake up other workers before return.
+     *
+     * @param w the worker (via its WorkQueue)
+     * @return a task or null if none found
+     */
+    private final ForkJoinTask<?> scan(WorkQueue w) {
+        WorkQueue[] ws; int m;
+        int ps = plock;                          // read plock before ws
+        if (w != null && (ws = workQueues) != null && (m = ws.length - 1) >= 0) {
+            int ec = w.eventCount;               // ec is negative if inactive
+            int r = w.seed; r ^= r << 13; r ^= r >>> 17; w.seed = r ^= r << 5;
+            w.hint = -1;                         // update seed and clear hint
+            int j = ((m + m + 1) | MIN_SCAN) & MAX_SCAN;
+            do {
+                WorkQueue q; ForkJoinTask<?>[] a; int b;
+                if ((q = ws[(r + j) & m]) != null && (b = q.base) - q.top < 0 &&
+                    (a = q.array) != null) {     // probably nonempty
+                    int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                    ForkJoinTask<?> t = (ForkJoinTask<?>)
+                        U.getObjectVolatile(a, i);
+                    if (q.base == b && ec >= 0 && t != null &&
+                        U.compareAndSwapObject(a, i, t, null)) {
+                        if ((q.base = b + 1) - q.top < 0)
+                            signalWork(q);
+                        return t;                // taken
+                    }
+                    else if ((ec < 0 || j < m) && (int)(ctl >> AC_SHIFT) <= 0) {
+                        w.hint = (r + j) & m;    // help signal below
+                        break;                   // cannot take
+                    }
+                }
+            } while (--j >= 0);
+
+            int h, e, ns; long c, sc; WorkQueue q;
+            if ((ns = w.nsteals) != 0) {
+                if (U.compareAndSwapLong(this, STEALCOUNT,
+                                         sc = stealCount, sc + ns))
+                    w.nsteals = 0;               // collect steals and rescan
+            }
+            else if (plock != ps)                // consistency check
+                ;                                // skip
+            else if ((e = (int)(c = ctl)) < 0)
+                w.qlock = -1;                    // pool is terminating
+            else {
+                if ((h = w.hint) < 0) {
+                    if (ec >= 0) {               // try to enqueue/inactivate
+                        long nc = (((long)ec |
+                                    ((c - AC_UNIT) & (AC_MASK|TC_MASK))));
+                        w.nextWait = e;          // link and mark inactive
+                        w.eventCount = ec | INT_SIGN;
+                        if (ctl != c || !U.compareAndSwapLong(this, CTL, c, nc))
+                            w.eventCount = ec;   // unmark on CAS failure
+                        else if ((int)(c >> AC_SHIFT) == 1 - (config & SMASK))
+                            idleAwaitWork(w, nc, c);
+                    }
+                    else if (w.eventCount < 0 && !tryTerminate(false, false) &&
+                             ctl == c) {         // block
+                        Thread wt = Thread.currentThread();
+                        Thread.interrupted();    // clear status
+                        U.putObject(wt, PARKBLOCKER, this);
+                        w.parker = wt;           // emulate LockSupport.park
+                        if (w.eventCount < 0)    // recheck
+                            U.park(false, 0L);
+                        w.parker = null;
+                        U.putObject(wt, PARKBLOCKER, null);
+                    }
+                }
+                if ((h >= 0 || (h = w.hint) >= 0) &&
+                    (ws = workQueues) != null && h < ws.length &&
+                    (q = ws[h]) != null) {      // signal others before retry
+                    WorkQueue v; Thread p; int u, i, s;
+                    for (int n = (config & SMASK) >>> 1;;) {
+                        int idleCount = (w.eventCount < 0) ? 0 : -1;
+                        if (((s = idleCount - q.base + q.top) <= n &&
+                             (n = s) <= 0) ||
+                            (u = (int)((c = ctl) >>> 32)) >= 0 ||
+                            (e = (int)c) <= 0 || m < (i = e & SMASK) ||
+                            (v = ws[i]) == null)
+                            break;
+                        long nc = (((long)(v.nextWait & E_MASK)) |
+                                   ((long)(u + UAC_UNIT) << 32));
+                        if (v.eventCount != (e | INT_SIGN) ||
+                            !U.compareAndSwapLong(this, CTL, c, nc))
+                            break;
+                        v.hint = h;
+                        v.eventCount = (e + E_SEQ) & E_MASK;
+                        if ((p = v.parker) != null)
+                            U.unpark(p);
+                        if (--n <= 0)
+                            break;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * If inactivating worker w has caused the pool to become
+     * quiescent, checks for pool termination, and, so long as this is
+     * not the only worker, waits for event for up to a given
+     * duration.  On timeout, if ctl has not changed, terminates the
+     * worker, which will in turn wake up another worker to possibly
+     * repeat this process.
+     *
+     * @param w the calling worker
+     * @param currentCtl the ctl value triggering possible quiescence
+     * @param prevCtl the ctl value to restore if thread is terminated
+     */
+    private void idleAwaitWork(WorkQueue w, long currentCtl, long prevCtl) {
+        if (w != null && w.eventCount < 0 &&
+            !tryTerminate(false, false) && (int)prevCtl != 0) {
+            int dc = -(short)(currentCtl >>> TC_SHIFT);
+            long parkTime = dc < 0 ? FAST_IDLE_TIMEOUT: (dc + 1) * IDLE_TIMEOUT;
+            long deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
+            Thread wt = Thread.currentThread();
+            while (ctl == currentCtl) {
+                Thread.interrupted();  // timed variant of version in scan()
+                U.putObject(wt, PARKBLOCKER, this);
+                w.parker = wt;
+                if (ctl == currentCtl)
+                    U.park(false, parkTime);
+                w.parker = null;
+                U.putObject(wt, PARKBLOCKER, null);
+                if (ctl != currentCtl)
+                    break;
+                if (deadline - System.nanoTime() <= 0L &&
+                    U.compareAndSwapLong(this, CTL, currentCtl, prevCtl)) {
+                    w.eventCount = (w.eventCount + E_SEQ) | E_MASK;
+                    w.qlock = -1;   // shrink
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Scans through queues looking for work while joining a task; if
+     * any present, signals. May return early if more signalling is
+     * detectably unneeded.
+     *
+     * @param task return early if done
+     * @param origin an index to start scan
+     */
+    private void helpSignal(ForkJoinTask<?> task, int origin) {
+        WorkQueue[] ws; WorkQueue w; Thread p; long c; int m, u, e, i, s;
+        if (task != null && task.status >= 0 &&
+            (u = (int)(ctl >>> 32)) < 0 && (u >> UAC_SHIFT) < 0 &&
+            (ws = workQueues) != null && (m = ws.length - 1) >= 0) {
+            outer: for (int k = origin, j = m; j >= 0; --j) {
+                WorkQueue q = ws[k++ & m];
+                for (int n = m;;) { // limit to at most m signals
+                    if (task.status < 0)
+                        break outer;
+                    if (q == null ||
+                        ((s = -q.base + q.top) <= n && (n = s) <= 0))
+                        break;
+                    if ((u = (int)((c = ctl) >>> 32)) >= 0 ||
+                        (e = (int)c) <= 0 || m < (i = e & SMASK) ||
+                        (w = ws[i]) == null)
+                        break outer;
+                    long nc = (((long)(w.nextWait & E_MASK)) |
+                               ((long)(u + UAC_UNIT) << 32));
+                    if (w.eventCount != (e | INT_SIGN))
+                        break outer;
+                    if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                        w.eventCount = (e + E_SEQ) & E_MASK;
+                        if ((p = w.parker) != null)
+                            U.unpark(p);
+                        if (--n <= 0)
                             break;
                     }
                 }
@@ -1171,201 +1852,630 @@
     }
 
     /**
-     * Final callback from terminating worker.  Removes record of
-     * worker from array, and adjusts counts. If pool is shutting
-     * down, tries to complete termination.
+     * Tries to locate and execute tasks for a stealer of the given
+     * task, or in turn one of its stealers, Traces currentSteal ->
+     * currentJoin links looking for a thread working on a descendant
+     * of the given task and with a non-empty queue to steal back and
+     * execute tasks from. The first call to this method upon a
+     * waiting join will often entail scanning/search, (which is OK
+     * because the joiner has nothing better to do), but this method
+     * leaves hints in workers to speed up subsequent calls. The
+     * implementation is very branchy to cope with potential
+     * inconsistencies or loops encountering chains that are stale,
+     * unknown, or so long that they are likely cyclic.
      *
-     * @param w the worker
+     * @param joiner the joining worker
+     * @param task the task to join
+     * @return 0 if no progress can be made, negative if task
+     * known complete, else positive
      */
-    final void deregisterWorker(ForkJoinWorkerThread w, Throwable ex) {
-        int idx = w.poolIndex;
-        int sc = w.stealCount;
-        int steps = 0;
-        // Remove from array, adjust worker counts and collect steal count.
-        // We can intermix failed removes or adjusts with steal updates
-        do {
-            long s, c;
-            int g;
-            if (steps == 0 && ((g = scanGuard) & SG_UNIT) == 0 &&
-                UNSAFE.compareAndSwapInt(this, scanGuardOffset,
-                                         g, g |= SG_UNIT)) {
-                ForkJoinWorkerThread[] ws = workers;
-                if (ws != null && idx >= 0 &&
-                    idx < ws.length && ws[idx] == w)
-                    ws[idx] = null;    // verify
-                nextWorkerIndex = idx;
-                scanGuard = g + SG_UNIT;
-                steps = 1;
-            }
-            if (steps == 1 &&
-                UNSAFE.compareAndSwapLong(this, ctlOffset, c = ctl,
-                                          (((c - AC_UNIT) & AC_MASK) |
-                                           ((c - TC_UNIT) & TC_MASK) |
-                                           (c & ~(AC_MASK|TC_MASK)))))
-                steps = 2;
-            if (sc != 0 &&
-                UNSAFE.compareAndSwapLong(this, stealCountOffset,
-                                          s = stealCount, s + sc))
-                sc = 0;
-        } while (steps != 2 || sc != 0);
-        if (!tryTerminate(false)) {
-            if (ex != null)   // possibly replace if died abnormally
-                signalWork();
-            else
-                tryReleaseWaiter();
-        }
-    }
-
-    // Shutdown and termination
-
-    /**
-     * Possibly initiates and/or completes termination.
-     *
-     * @param now if true, unconditionally terminate, else only
-     * if shutdown and empty queue and no active workers
-     * @return true if now terminating or terminated
-     */
-    private boolean tryTerminate(boolean now) {
-        long c;
-        while (((c = ctl) & STOP_BIT) == 0) {
-            if (!now) {
-                if ((int)(c >> AC_SHIFT) != -parallelism)
-                    return false;
-                if (!shutdown || blockedCount != 0 || quiescerCount != 0 ||
-                    queueBase != queueTop) {
-                    if (ctl == c) // staleness check
-                        return false;
-                    continue;
-                }
-            }
-            if (UNSAFE.compareAndSwapLong(this, ctlOffset, c, c | STOP_BIT))
-                startTerminating();
-        }
-        if ((short)(c >>> TC_SHIFT) == -parallelism) { // signal when 0 workers
-            final ReentrantLock lock = this.submissionLock;
-            lock.lock();
-            try {
-                termination.signalAll();
-            } finally {
-                lock.unlock();
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Runs up to three passes through workers: (0) Setting
-     * termination status for each worker, followed by wakeups up to
-     * queued workers; (1) helping cancel tasks; (2) interrupting
-     * lagging threads (likely in external tasks, but possibly also
-     * blocked in joins).  Each pass repeats previous steps because of
-     * potential lagging thread creation.
-     */
-    private void startTerminating() {
-        cancelSubmissions();
-        for (int pass = 0; pass < 3; ++pass) {
-            ForkJoinWorkerThread[] ws = workers;
-            if (ws != null) {
-                for (ForkJoinWorkerThread w : ws) {
-                    if (w != null) {
-                        w.terminate = true;
-                        if (pass > 0) {
-                            w.cancelTasks();
-                            if (pass > 1 && !w.isInterrupted()) {
-                                try {
-                                    w.interrupt();
-                                } catch (SecurityException ignore) {
-                                }
+    private int tryHelpStealer(WorkQueue joiner, ForkJoinTask<?> task) {
+        int stat = 0, steps = 0;                    // bound to avoid cycles
+        if (joiner != null && task != null) {       // hoist null checks
+            restart: for (;;) {
+                ForkJoinTask<?> subtask = task;     // current target
+                for (WorkQueue j = joiner, v;;) {   // v is stealer of subtask
+                    WorkQueue[] ws; int m, s, h;
+                    if ((s = task.status) < 0) {
+                        stat = s;
+                        break restart;
+                    }
+                    if ((ws = workQueues) == null || (m = ws.length - 1) <= 0)
+                        break restart;              // shutting down
+                    if ((v = ws[h = (j.hint | 1) & m]) == null ||
+                        v.currentSteal != subtask) {
+                        for (int origin = h;;) {    // find stealer
+                            if (((h = (h + 2) & m) & 15) == 1 &&
+                                (subtask.status < 0 || j.currentJoin != subtask))
+                                continue restart;   // occasional staleness check
+                            if ((v = ws[h]) != null &&
+                                v.currentSteal == subtask) {
+                                j.hint = h;        // save hint
+                                break;
+                            }
+                            if (h == origin)
+                                break restart;      // cannot find stealer
+                        }
+                    }
+                    for (;;) { // help stealer or descend to its stealer
+                        ForkJoinTask[] a;  int b;
+                        if (subtask.status < 0)     // surround probes with
+                            continue restart;       //   consistency checks
+                        if ((b = v.base) - v.top < 0 && (a = v.array) != null) {
+                            int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+                            ForkJoinTask<?> t =
+                                (ForkJoinTask<?>)U.getObjectVolatile(a, i);
+                            if (subtask.status < 0 || j.currentJoin != subtask ||
+                                v.currentSteal != subtask)
+                                continue restart;   // stale
+                            stat = 1;               // apparent progress
+                            if (t != null && v.base == b &&
+                                U.compareAndSwapObject(a, i, t, null)) {
+                                v.base = b + 1;     // help stealer
+                                joiner.runSubtask(t);
+                            }
+                            else if (v.base == b && ++steps == MAX_HELP)
+                                break restart;      // v apparently stalled
+                        }
+                        else {                      // empty -- try to descend
+                            ForkJoinTask<?> next = v.currentJoin;
+                            if (subtask.status < 0 || j.currentJoin != subtask ||
+                                v.currentSteal != subtask)
+                                continue restart;   // stale
+                            else if (next == null || ++steps == MAX_HELP)
+                                break restart;      // dead-end or maybe cyclic
+                            else {
+                                subtask = next;
+                                j = v;
+                                break;
                             }
                         }
                     }
                 }
-                terminateWaiters();
             }
         }
+        return stat;
+    }
+
+    /**
+     * Analog of tryHelpStealer for CountedCompleters. Tries to steal
+     * and run tasks within the target's computation.
+     *
+     * @param task the task to join
+     * @param mode if shared, exit upon completing any task
+     * if all workers are active
+     */
+    private int helpComplete(ForkJoinTask<?> task, int mode) {
+        WorkQueue[] ws; WorkQueue q; int m, n, s, u;
+        if (task != null && (ws = workQueues) != null &&
+            (m = ws.length - 1) >= 0) {
+            for (int j = 1, origin = j;;) {
+                if ((s = task.status) < 0)
+                    return s;
+                if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) {
+                    origin = j;
+                    if (mode == SHARED_QUEUE &&
+                        ((u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0))
+                        break;
+                }
+                else if ((j = (j + 2) & m) == origin)
+                    break;
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Tries to decrement active count (sometimes implicitly) and
+     * possibly release or create a compensating worker in preparation
+     * for blocking. Fails on contention or termination. Otherwise,
+     * adds a new thread if no idle workers are available and pool
+     * may become starved.
+     */
+    final boolean tryCompensate() {
+        int pc = config & SMASK, e, i, tc; long c;
+        WorkQueue[] ws; WorkQueue w; Thread p;
+        if ((ws = workQueues) != null && (e = (int)(c = ctl)) >= 0) {
+            if (e != 0 && (i = e & SMASK) < ws.length &&
+                (w = ws[i]) != null && w.eventCount == (e | INT_SIGN)) {
+                long nc = ((long)(w.nextWait & E_MASK) |
+                           (c & (AC_MASK|TC_MASK)));
+                if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                    w.eventCount = (e + E_SEQ) & E_MASK;
+                    if ((p = w.parker) != null)
+                        U.unpark(p);
+                    return true;   // replace with idle worker
+                }
+            }
+            else if ((tc = (short)(c >>> TC_SHIFT)) >= 0 &&
+                     (int)(c >> AC_SHIFT) + pc > 1) {
+                long nc = ((c - AC_UNIT) & AC_MASK) | (c & ~AC_MASK);
+                if (U.compareAndSwapLong(this, CTL, c, nc))
+                    return true;   // no compensation
+            }
+            else if (tc + pc < MAX_CAP) {
+                long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK);
+                if (U.compareAndSwapLong(this, CTL, c, nc)) {
+                    ForkJoinWorkerThreadFactory fac;
+                    Throwable ex = null;
+                    ForkJoinWorkerThread wt = null;
+                    try {
+                        if ((fac = factory) != null &&
+                            (wt = fac.newThread(this)) != null) {
+                            wt.start();
+                            return true;
+                        }
+                    } catch (Throwable rex) {
+                        ex = rex;
+                    }
+                    deregisterWorker(wt, ex); // clean up and return false
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Helps and/or blocks until the given task is done.
+     *
+     * @param joiner the joining worker
+     * @param task the task
+     * @return task status on exit
+     */
+    final int awaitJoin(WorkQueue joiner, ForkJoinTask<?> task) {
+        int s = 0;
+        if (joiner != null && task != null && (s = task.status) >= 0) {
+            ForkJoinTask<?> prevJoin = joiner.currentJoin;
+            joiner.currentJoin = task;
+            do {} while ((s = task.status) >= 0 && !joiner.isEmpty() &&
+                         joiner.tryRemoveAndExec(task)); // process local tasks
+            if (s >= 0 && (s = task.status) >= 0) {
+                helpSignal(task, joiner.poolIndex);
+                if ((s = task.status) >= 0 &&
+                    (task instanceof CountedCompleter))
+                    s = helpComplete(task, LIFO_QUEUE);
+            }
+            while (s >= 0 && (s = task.status) >= 0) {
+                if ((!joiner.isEmpty() ||           // try helping
+                     (s = tryHelpStealer(joiner, task)) == 0) &&
+                    (s = task.status) >= 0) {
+                    helpSignal(task, joiner.poolIndex);
+                    if ((s = task.status) >= 0 && tryCompensate()) {
+                        if (task.trySetSignal() && (s = task.status) >= 0) {
+                            synchronized (task) {
+                                if (task.status >= 0) {
+                                    try {                // see ForkJoinTask
+                                        task.wait();     //  for explanation
+                                    } catch (InterruptedException ie) {
+                                    }
+                                }
+                                else
+                                    task.notifyAll();
+                            }
+                        }
+                        long c;                          // re-activate
+                        do {} while (!U.compareAndSwapLong
+                                     (this, CTL, c = ctl, c + AC_UNIT));
+                    }
+                }
+            }
+            joiner.currentJoin = prevJoin;
+        }
+        return s;
+    }
+
+    /**
+     * Stripped-down variant of awaitJoin used by timed joins. Tries
+     * to help join only while there is continuous progress. (Caller
+     * will then enter a timed wait.)
+     *
+     * @param joiner the joining worker
+     * @param task the task
+     */
+    final void helpJoinOnce(WorkQueue joiner, ForkJoinTask<?> task) {
+        int s;
+        if (joiner != null && task != null && (s = task.status) >= 0) {
+            ForkJoinTask<?> prevJoin = joiner.currentJoin;
+            joiner.currentJoin = task;
+            do {} while ((s = task.status) >= 0 && !joiner.isEmpty() &&
+                         joiner.tryRemoveAndExec(task));
+            if (s >= 0 && (s = task.status) >= 0) {
+                helpSignal(task, joiner.poolIndex);
+                if ((s = task.status) >= 0 &&
+                    (task instanceof CountedCompleter))
+                    s = helpComplete(task, LIFO_QUEUE);
+            }
+            if (s >= 0 && joiner.isEmpty()) {
+                do {} while (task.status >= 0 &&
+                             tryHelpStealer(joiner, task) > 0);
+            }
+            joiner.currentJoin = prevJoin;
+        }
     }
 
     /**
-     * Polls and cancels all submissions. Called only during termination.
+     * Returns a (probably) non-empty steal queue, if one is found
+     * during a random, then cyclic scan, else null.  This method must
+     * be retried by caller if, by the time it tries to use the queue,
+     * it is empty.
+     * @param r a (random) seed for scanning
      */
-    private void cancelSubmissions() {
-        while (queueBase != queueTop) {
-            ForkJoinTask<?> task = pollSubmission();
-            if (task != null) {
-                try {
-                    task.cancel(false);
-                } catch (Throwable ignore) {
+    private WorkQueue findNonEmptyStealQueue(int r) {
+        for (WorkQueue[] ws;;) {
+            int ps = plock, m, n;
+            if ((ws = workQueues) == null || (m = ws.length - 1) < 1)
+                return null;
+            for (int j = (m + 1) << 2; ;) {
+                WorkQueue q = ws[(((r + j) << 1) | 1) & m];
+                if (q != null && (n = q.base - q.top) < 0) {
+                    if (n < -1)
+                        signalWork(q);
+                    return q;
+                }
+                else if (--j < 0) {
+                    if (plock == ps)
+                        return null;
+                    break;
                 }
             }
         }
     }
 
     /**
-     * Tries to set the termination status of waiting workers, and
-     * then wakes them up (after which they will terminate).
+     * Runs tasks until {@code isQuiescent()}. We piggyback on
+     * active count ctl maintenance, but rather than blocking
+     * when tasks cannot be found, we rescan until all others cannot
+     * find tasks either.
      */
-    private void terminateWaiters() {
-        ForkJoinWorkerThread[] ws = workers;
-        if (ws != null) {
-            ForkJoinWorkerThread w; long c; int i, e;
-            int n = ws.length;
-            while ((i = ~(e = (int)(c = ctl)) & SMASK) < n &&
-                   (w = ws[i]) != null && w.eventCount == (e & E_MASK)) {
-                if (UNSAFE.compareAndSwapLong(this, ctlOffset, c,
-                                              (long)(w.nextWait & E_MASK) |
-                                              ((c + AC_UNIT) & AC_MASK) |
-                                              (c & (TC_MASK|STOP_BIT)))) {
-                    w.terminate = true;
-                    w.eventCount = e + EC_UNIT;
-                    if (w.parked)
-                        UNSAFE.unpark(w);
+    final void helpQuiescePool(WorkQueue w) {
+        for (boolean active = true;;) {
+            ForkJoinTask<?> localTask; // exhaust local queue
+            while ((localTask = w.nextLocalTask()) != null)
+                localTask.doExec();
+            // Similar to loop in scan(), but ignoring submissions
+            WorkQueue q = findNonEmptyStealQueue(w.nextSeed());
+            if (q != null) {
+                ForkJoinTask<?> t; int b;
+                if (!active) {      // re-establish active count
+                    long c;
+                    active = true;
+                    do {} while (!U.compareAndSwapLong
+                                 (this, CTL, c = ctl, c + AC_UNIT));
+                }
+                if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
+                    w.runSubtask(t);
+            }
+            else {
+                long c;
+                if (active) {       // decrement active count without queuing
+                    active = false;
+                    do {} while (!U.compareAndSwapLong
+                                 (this, CTL, c = ctl, c -= AC_UNIT));
+                }
+                else
+                    c = ctl;        // re-increment on exit
+                if ((int)(c >> AC_SHIFT) + (config & SMASK) == 0) {
+                    do {} while (!U.compareAndSwapLong
+                                 (this, CTL, c = ctl, c + AC_UNIT));
+                    break;
                 }
             }
         }
     }
 
-    // misc ForkJoinWorkerThread support
-
     /**
-     * Increments or decrements quiescerCount. Needed only to prevent
-     * triggering shutdown if a worker is transiently inactive while
-     * checking quiescence.
+     * Gets and removes a local or stolen task for the given worker.
      *
-     * @param delta 1 for increment, -1 for decrement
+     * @return a task, if available
      */
-    final void addQuiescerCount(int delta) {
-        int c;
-        do {} while (!UNSAFE.compareAndSwapInt(this, quiescerCountOffset,
-                                               c = quiescerCount, c + delta));
+    final ForkJoinTask<?> nextTaskFor(WorkQueue w) {
+        for (ForkJoinTask<?> t;;) {
+            WorkQueue q; int b;
+            if ((t = w.nextLocalTask()) != null)
+                return t;
+            if ((q = findNonEmptyStealQueue(w.nextSeed())) == null)
+                return null;
+            if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
+                return t;
+        }
     }
 
     /**
-     * Directly increments or decrements active count without queuing.
-     * This method is used to transiently assert inactivation while
-     * checking quiescence.
+     * Returns a cheap heuristic guide for task partitioning when
+     * programmers, frameworks, tools, or languages have little or no
+     * idea about task granularity.  In essence by offering this
+     * method, we ask users only about tradeoffs in overhead vs
+     * expected throughput and its variance, rather than how finely to
+     * partition tasks.
      *
-     * @param delta 1 for increment, -1 for decrement
+     * In a steady state strict (tree-structured) computation, each
+     * thread makes available for stealing enough tasks for other
+     * threads to remain active. Inductively, if all threads play by
+     * the same rules, each thread should make available only a
+     * constant number of tasks.
+     *
+     * The minimum useful constant is just 1. But using a value of 1
+     * would require immediate replenishment upon each steal to
+     * maintain enough tasks, which is infeasible.  Further,
+     * partitionings/granularities of offered tasks should minimize
+     * steal rates, which in general means that threads nearer the top
+     * of computation tree should generate more than those nearer the
+     * bottom. In perfect steady state, each thread is at
+     * approximately the same level of computation tree. However,
+     * producing extra tasks amortizes the uncertainty of progress and
+     * diffusion assumptions.
+     *
+     * So, users will want to use values larger (but not much larger)
+     * than 1 to both smooth over transient shortages and hedge
+     * against uneven progress; as traded off against the cost of
+     * extra task overhead. We leave the user to pick a threshold
+     * value to compare with the results of this call to guide
+     * decisions, but recommend values such as 3.
+     *
+     * When all threads are active, it is on average OK to estimate
+     * surplus strictly locally. In steady-state, if one thread is
+     * maintaining say 2 surplus tasks, then so are others. So we can
+     * just use estimated queue length.  However, this strategy alone
+     * leads to serious mis-estimates in some non-steady-state
+     * conditions (ramp-up, ramp-down, other stalls). We can detect
+     * many of these by further considering the number of "idle"
+     * threads, that are known to have zero queued tasks, so
+     * compensate by a factor of (#idle/#active) threads.
+     *
+     * Note: The approximation of #busy workers as #active workers is
+     * not very good under current signalling scheme, and should be
+     * improved.
      */
-    final void addActiveCount(int delta) {
-        long d = (long)delta << AC_SHIFT;
-        long c;
-        do {} while (!UNSAFE.compareAndSwapLong(this, ctlOffset,
-                                                c = ctl, c + d));
+    static int getSurplusQueuedTaskCount() {
+        Thread t; ForkJoinWorkerThread wt; ForkJoinPool pool; WorkQueue q;
+        if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)) {
+            int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).config & SMASK;
+            int n = (q = wt.workQueue).top - q.base;
+            int a = (int)(pool.ctl >> AC_SHIFT) + p;
+            return n - (a > (p >>>= 1) ? 0 :
+                        a > (p >>>= 1) ? 1 :
+                        a > (p >>>= 1) ? 2 :
+                        a > (p >>>= 1) ? 4 :
+                        8);
+        }
+        return 0;
+    }
+
+    //  Termination
+
+    /**
+     * Possibly initiates and/or completes termination.  The caller
+     * triggering termination runs three passes through workQueues:
+     * (0) Setting termination status, followed by wakeups of queued
+     * workers; (1) cancelling all tasks; (2) interrupting lagging
+     * threads (likely in external tasks, but possibly also blocked in
+     * joins).  Each pass repeats previous steps because of potential
+     * lagging thread creation.
+     *
+     * @param now if true, unconditionally terminate, else only
+     * if no work and no active workers
+     * @param enable if true, enable shutdown when next possible
+     * @return true if now terminating or terminated
+     */
+    private boolean tryTerminate(boolean now, boolean enable) {
+        if (this == commonPool)                     // cannot shut down
+            return false;
+        for (long c;;) {
+            if (((c = ctl) & STOP_BIT) != 0) {      // already terminating
+                if ((short)(c >>> TC_SHIFT) == -(config & SMASK)) {
+                    synchronized (this) {
+                        notifyAll();                // signal when 0 workers
+                    }
+                }
+                return true;
+            }
+            if (plock >= 0) {                       // not yet enabled
+                int ps;
+                if (!enable)
+                    return false;
+                if (((ps = plock) & PL_LOCK) != 0 ||
+                    !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+                    ps = acquirePlock();
+                if (!U.compareAndSwapInt(this, PLOCK, ps, SHUTDOWN))
+                    releasePlock(SHUTDOWN);
+            }
+            if (!now) {                             // check if idle & no tasks
+                if ((int)(c >> AC_SHIFT) != -(config & SMASK) ||
+                    hasQueuedSubmissions())
+                    return false;
+                // Check for unqueued inactive workers. One pass suffices.
+                WorkQueue[] ws = workQueues; WorkQueue w;
+                if (ws != null) {
+                    for (int i = 1; i < ws.length; i += 2) {
+                        if ((w = ws[i]) != null && w.eventCount >= 0)
+                            return false;
+                    }
+                }
+            }
+            if (U.compareAndSwapLong(this, CTL, c, c | STOP_BIT)) {
+                for (int pass = 0; pass < 3; ++pass) {
+                    WorkQueue[] ws = workQueues;
+                    if (ws != null) {
+                        WorkQueue w; Thread wt;
+                        int n = ws.length;
+                        for (int i = 0; i < n; ++i) {
+                            if ((w = ws[i]) != null) {
+                                w.qlock = -1;
+                                if (pass > 0) {
+                                    w.cancelAll();
+                                    if (pass > 1 && (wt = w.owner) != null) {
+                                        if (!wt.isInterrupted()) {
+                                            try {
+                                                wt.interrupt();
+                                            } catch (SecurityException ignore) {
+                                            }
+                                        }
+                                        U.unpark(wt);
+                                    }
+                                }
+                            }
+                        }
+                        // Wake up workers parked on event queue
+                        int i, e; long cc; Thread p;
+                        while ((e = (int)(cc = ctl) & E_MASK) != 0 &&
+                               (i = e & SMASK) < n &&
+                               (w = ws[i]) != null) {
+                            long nc = ((long)(w.nextWait & E_MASK) |
+                                       ((cc + AC_UNIT) & AC_MASK) |
+                                       (cc & (TC_MASK|STOP_BIT)));
+                            if (w.eventCount == (e | INT_SIGN) &&
+                                U.compareAndSwapLong(this, CTL, cc, nc)) {
+                                w.eventCount = (e + E_SEQ) & E_MASK;
+                                w.qlock = -1;
+                                if ((p = w.parker) != null)
+                                    U.unpark(p);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // external operations on common pool
+
+    /**
+     * Returns common pool queue for a thread that has submitted at
+     * least one task.
+     */
+    static WorkQueue commonSubmitterQueue() {
+        ForkJoinPool p; WorkQueue[] ws; int m; Submitter z;
+        return ((z = submitters.get()) != null &&
+                (p = commonPool) != null &&
+                (ws = p.workQueues) != null &&
+                (m = ws.length - 1) >= 0) ?
+            ws[m & z.seed & SQMASK] : null;
     }
 
     /**
-     * Returns the approximate (non-atomic) number of idle threads per
-     * active thread.
+     * Tries to pop the given task from submitter's queue in common pool.
      */
-    final int idlePerActive() {
-        // Approximate at powers of two for small values, saturate past 4
-        int p = parallelism;
-        int a = p + (int)(ctl >> AC_SHIFT);
-        return (a > (p >>>= 1) ? 0 :
-                a > (p >>>= 1) ? 1 :
-                a > (p >>>= 1) ? 2 :
-                a > (p >>>= 1) ? 4 :
-                8);
+    static boolean tryExternalUnpush(ForkJoinTask<?> t) {
+        ForkJoinPool p; WorkQueue[] ws; WorkQueue q; Submitter z;
+        ForkJoinTask<?>[] a;  int m, s;
+        if (t != null &&
+            (z = submitters.get()) != null &&
+            (p = commonPool) != null &&
+            (ws = p.workQueues) != null &&
+            (m = ws.length - 1) >= 0 &&
+            (q = ws[m & z.seed & SQMASK]) != null &&
+            (s = q.top) != q.base &&
+            (a = q.array) != null) {
+            long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
+            if (U.getObject(a, j) == t &&
+                U.compareAndSwapInt(q, QLOCK, 0, 1)) {
+                if (q.array == a && q.top == s && // recheck
+                    U.compareAndSwapObject(a, j, t, null)) {
+                    q.top = s - 1;
+                    q.qlock = 0;
+                    return true;
+                }
+                q.qlock = 0;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Tries to pop and run local tasks within the same computation
+     * as the given root. On failure, tries to help complete from
+     * other queues via helpComplete.
+     */
+    private void externalHelpComplete(WorkQueue q, ForkJoinTask<?> root) {
+        ForkJoinTask<?>[] a; int m;
+        if (q != null && (a = q.array) != null && (m = (a.length - 1)) >= 0 &&
+            root != null && root.status >= 0) {
+            for (;;) {
+                int s, u; Object o; CountedCompleter<?> task = null;
+                if ((s = q.top) - q.base > 0) {
+                    long j = ((m & (s - 1)) << ASHIFT) + ABASE;
+                    if ((o = U.getObject(a, j)) != null &&
+                        (o instanceof CountedCompleter)) {
+                        CountedCompleter<?> t = (CountedCompleter<?>)o, r = t;
+                        do {
+                            if (r == root) {
+                                if (U.compareAndSwapInt(q, QLOCK, 0, 1)) {
+                                    if (q.array == a && q.top == s &&
+                                        U.compareAndSwapObject(a, j, t, null)) {
+                                        q.top = s - 1;
+                                        task = t;
+                                    }
+                                    q.qlock = 0;
+                                }
+                                break;
+                            }
+                        } while ((r = r.completer) != null);
+                    }
+                }
+                if (task != null)
+                    task.doExec();
+                if (root.status < 0 ||
+                    (u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0)
+                    break;
+                if (task == null) {
+                    helpSignal(root, q.poolIndex);
+                    if (root.status >= 0)
+                        helpComplete(root, SHARED_QUEUE);
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Tries to help execute or signal availability of the given task
+     * from submitter's queue in common pool.
+     */
+    static void externalHelpJoin(ForkJoinTask<?> t) {
+        // Some hard-to-avoid overlap with tryExternalUnpush
+        ForkJoinPool p; WorkQueue[] ws; WorkQueue q, w; Submitter z;
+        ForkJoinTask<?>[] a;  int m, s, n;
+        if (t != null &&
+            (z = submitters.get()) != null &&
+            (p = commonPool) != null &&
+            (ws = p.workQueues) != null &&
+            (m = ws.length - 1) >= 0 &&
+            (q = ws[m & z.seed & SQMASK]) != null &&
+            (a = q.array) != null) {
+            int am = a.length - 1;
+            if ((s = q.top) != q.base) {
+                long j = ((am & (s - 1)) << ASHIFT) + ABASE;
+                if (U.getObject(a, j) == t &&
+                    U.compareAndSwapInt(q, QLOCK, 0, 1)) {
+                    if (q.array == a && q.top == s &&
+                        U.compareAndSwapObject(a, j, t, null)) {
+                        q.top = s - 1;
+                        q.qlock = 0;
+                        t.doExec();
+                    }
+                    else
+                        q.qlock = 0;
+                }
+            }
+            if (t.status >= 0) {
+                if (t instanceof CountedCompleter)
+                    p.externalHelpComplete(q, t);
+                else
+                    p.helpSignal(t, q.poolIndex);
+            }
+        }
+    }
+
+    /**
+     * Restricted version of helpQuiescePool for external callers
+     */
+    static void externalHelpQuiescePool() {
+        ForkJoinPool p; ForkJoinTask<?> t; WorkQueue q; int b;
+        if ((p = commonPool) != null &&
+            (q = p.findNonEmptyStealQueue(1)) != null &&
+            (b = q.base) - q.top < 0 &&
+            (t = q.pollAt(b)) != null)
+            t.doExec();
     }
 
     // Exported methods
@@ -1379,7 +2489,7 @@
      * no UncaughtExceptionHandler, and non-async LIFO processing mode.
      */
     public ForkJoinPool() {
-        this(Runtime.getRuntime().availableProcessors(),
+        this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
              defaultForkJoinWorkerThreadFactory, null, false);
     }
 
@@ -1424,31 +2534,46 @@
         checkPermission();
         if (factory == null)
             throw new NullPointerException();
-        if (parallelism <= 0 || parallelism > MAX_ID)
+        if (parallelism <= 0 || parallelism > MAX_CAP)
             throw new IllegalArgumentException();
-        this.parallelism = parallelism;
         this.factory = factory;
         this.ueh = handler;
-        this.locallyFifo = asyncMode;
+        this.config = parallelism | (asyncMode ? (FIFO_QUEUE << 16) : 0);
         long np = (long)(-parallelism); // offset ctl counts
         this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
-        this.submissionQueue = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY];
-        // initialize workers array with room for 2*parallelism if possible
-        int n = parallelism << 1;
-        if (n >= MAX_ID)
-            n = MAX_ID;
-        else { // See Hackers Delight, sec 3.2, where n < (1 << 16)
-            n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8;
-        }
-        workers = new ForkJoinWorkerThread[n + 1];
-        this.submissionLock = new ReentrantLock();
-        this.termination = submissionLock.newCondition();
+        int pn = nextPoolId();
         StringBuilder sb = new StringBuilder("ForkJoinPool-");
-        sb.append(poolNumberGenerator.incrementAndGet());
+        sb.append(Integer.toString(pn));
         sb.append("-worker-");
         this.workerNamePrefix = sb.toString();
     }
 
+    /**
+     * Constructor for common pool, suitable only for static initialization.
+     * Basically the same as above, but uses smallest possible initial footprint.
+     */
+    ForkJoinPool(int parallelism, long ctl,
+                 ForkJoinWorkerThreadFactory factory,
+                 Thread.UncaughtExceptionHandler handler) {
+        this.config = parallelism;
+        this.ctl = ctl;
+        this.factory = factory;
+        this.ueh = handler;
+        this.workerNamePrefix = "ForkJoinPool.commonPool-worker-";
+    }
+
+    /**
+     * Returns the common pool instance.
+     *
+     * @return the common pool instance
+     * @since 1.8
+     * @hide
+     */
+    public static ForkJoinPool commonPool() {
+        // assert commonPool != null : "static init error";
+        return commonPool;
+    }
+
     // Execution methods
 
     /**
@@ -1468,34 +2593,10 @@
      *         scheduled for execution
      */
     public <T> T invoke(ForkJoinTask<T> task) {
-        Thread t = Thread.currentThread();
         if (task == null)
             throw new NullPointerException();
-        if (shutdown)
-            throw new RejectedExecutionException();
-        if ((t instanceof ForkJoinWorkerThread) &&
-            ((ForkJoinWorkerThread)t).pool == this)
-            return task.invoke();  // bypass submit if in same pool
-        else {
-            addSubmission(task);
-            return task.join();
-        }
-    }
-
-    /**
-     * Unless terminating, forks task if within an ongoing FJ
-     * computation in the current pool, else submits as external task.
-     */
-    private <T> void forkOrSubmit(ForkJoinTask<T> task) {
-        ForkJoinWorkerThread w;
-        Thread t = Thread.currentThread();
-        if (shutdown)
-            throw new RejectedExecutionException();
-        if ((t instanceof ForkJoinWorkerThread) &&
-            (w = (ForkJoinWorkerThread)t).pool == this)
-            w.pushTask(task);
-        else
-            addSubmission(task);
+        externalPush(task);
+        return task.join();
     }
 
     /**
@@ -1509,7 +2610,7 @@
     public void execute(ForkJoinTask<?> task) {
         if (task == null)
             throw new NullPointerException();
-        forkOrSubmit(task);
+        externalPush(task);
     }
 
     // AbstractExecutorService methods
@@ -1526,8 +2627,8 @@
         if (task instanceof ForkJoinTask<?>) // avoid re-wrap
             job = (ForkJoinTask<?>) task;
         else
-            job = ForkJoinTask.adapt(task, null);
-        forkOrSubmit(job);
+            job = new ForkJoinTask.AdaptedRunnableAction(task);
+        externalPush(job);
     }
 
     /**
@@ -1542,7 +2643,7 @@
     public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
         if (task == null)
             throw new NullPointerException();
-        forkOrSubmit(task);
+        externalPush(task);
         return task;
     }
 
@@ -1552,10 +2653,8 @@
      *         scheduled for execution
      */
     public <T> ForkJoinTask<T> submit(Callable<T> task) {
-        if (task == null)
-            throw new NullPointerException();
-        ForkJoinTask<T> job = ForkJoinTask.adapt(task);
-        forkOrSubmit(job);
+        ForkJoinTask<T> job = new ForkJoinTask.AdaptedCallable<T>(task);
+        externalPush(job);
         return job;
     }
 
@@ -1565,10 +2664,8 @@
      *         scheduled for execution
      */
     public <T> ForkJoinTask<T> submit(Runnable task, T result) {
-        if (task == null)
-            throw new NullPointerException();
-        ForkJoinTask<T> job = ForkJoinTask.adapt(task, result);
-        forkOrSubmit(job);
+        ForkJoinTask<T> job = new ForkJoinTask.AdaptedRunnable<T>(task, result);
+        externalPush(job);
         return job;
     }
 
@@ -1584,8 +2681,8 @@
         if (task instanceof ForkJoinTask<?>) // avoid re-wrap
             job = (ForkJoinTask<?>) task;
         else
-            job = ForkJoinTask.adapt(task, null);
-        forkOrSubmit(job);
+            job = new ForkJoinTask.AdaptedRunnableAction(task);
+        externalPush(job);
         return job;
     }
 
@@ -1594,25 +2691,27 @@
      * @throws RejectedExecutionException {@inheritDoc}
      */
     public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
-        ArrayList<ForkJoinTask<T>> forkJoinTasks =
-            new ArrayList<ForkJoinTask<T>>(tasks.size());
-        for (Callable<T> task : tasks)
-            forkJoinTasks.add(ForkJoinTask.adapt(task));
-        invoke(new InvokeAll<T>(forkJoinTasks));
+        // In previous versions of this class, this method constructed
+        // a task to run ForkJoinTask.invokeAll, but now external
+        // invocation of multiple tasks is at least as efficient.
+        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
 
-        @SuppressWarnings({"unchecked", "rawtypes"})
-            List<Future<T>> futures = (List<Future<T>>) (List) forkJoinTasks;
-        return futures;
-    }
-
-    static final class InvokeAll<T> extends RecursiveAction {
-        final ArrayList<ForkJoinTask<T>> tasks;
-        InvokeAll(ArrayList<ForkJoinTask<T>> tasks) { this.tasks = tasks; }
-        public void compute() {
-            try { invokeAll(tasks); }
-            catch (Exception ignore) {}
+        boolean done = false;
+        try {
+            for (Callable<T> t : tasks) {
+                ForkJoinTask<T> f = new ForkJoinTask.AdaptedCallable<T>(t);
+                futures.add(f);
+                externalPush(f);
+            }
+            for (int i = 0, size = futures.size(); i < size; i++)
+                ((ForkJoinTask<?>)futures.get(i)).quietlyJoin();
+            done = true;
+            return futures;
+        } finally {
+            if (!done)
+                for (int i = 0, size = futures.size(); i < size; i++)
+                    futures.get(i).cancel(false);
         }
-        private static final long serialVersionUID = -7914297376763021607L;
     }
 
     /**
@@ -1640,7 +2739,18 @@
      * @return the targeted parallelism level of this pool
      */
     public int getParallelism() {
-        return parallelism;
+        return config & SMASK;
+    }
+
+    /**
+     * Returns the targeted parallelism level of the common pool.
+     *
+     * @return the targeted parallelism level of the common pool
+     * @since 1.8
+     * @hide
+     */
+    public static int getCommonPoolParallelism() {
+        return commonPoolParallelism;
     }
 
     /**
@@ -1652,7 +2762,7 @@
      * @return the number of worker threads
      */
     public int getPoolSize() {
-        return parallelism + (short)(ctl >>> TC_SHIFT);
+        return (config & SMASK) + (short)(ctl >>> TC_SHIFT);
     }
 
     /**
@@ -1662,7 +2772,7 @@
      * @return {@code true} if this pool uses async mode
      */
     public boolean getAsyncMode() {
-        return locallyFifo;
+        return (config >>> 16) == FIFO_QUEUE;
     }
 
     /**
@@ -1674,8 +2784,15 @@
      * @return the number of worker threads
      */
     public int getRunningThreadCount() {
-        int r = parallelism + (int)(ctl >> AC_SHIFT);
-        return (r <= 0) ? 0 : r; // suppress momentarily negative values
+        int rc = 0;
+        WorkQueue[] ws; WorkQueue w;
+        if ((ws = workQueues) != null) {
+            for (int i = 1; i < ws.length; i += 2) {
+                if ((w = ws[i]) != null && w.isApparentlyUnblocked())
+                    ++rc;
+            }
+        }
+        return rc;
     }
 
     /**
@@ -1686,7 +2803,7 @@
      * @return the number of active threads
      */
     public int getActiveThreadCount() {
-        int r = parallelism + (int)(ctl >> AC_SHIFT) + blockedCount;
+        int r = (config & SMASK) + (int)(ctl >> AC_SHIFT);
         return (r <= 0) ? 0 : r; // suppress momentarily negative values
     }
 
@@ -1702,7 +2819,7 @@
      * @return {@code true} if all threads are currently idle
      */
     public boolean isQuiescent() {
-        return parallelism + (int)(ctl >> AC_SHIFT) + blockedCount == 0;
+        return (int)(ctl >> AC_SHIFT) + (config & SMASK) == 0;
     }
 
     /**
@@ -1717,7 +2834,15 @@
      * @return the number of steals
      */
     public long getStealCount() {
-        return stealCount;
+        long count = stealCount;
+        WorkQueue[] ws; WorkQueue w;
+        if ((ws = workQueues) != null) {
+            for (int i = 1; i < ws.length; i += 2) {
+                if ((w = ws[i]) != null)
+                    count += w.nsteals;
+            }
+        }
+        return count;
     }
 
     /**
@@ -1732,12 +2857,12 @@
      */
     public long getQueuedTaskCount() {
         long count = 0;
-        ForkJoinWorkerThread[] ws;
-        if ((short)(ctl >>> TC_SHIFT) > -parallelism &&
-            (ws = workers) != null) {
-            for (ForkJoinWorkerThread w : ws)
-                if (w != null)
-                    count -= w.queueBase - w.queueTop; // must read base first
+        WorkQueue[] ws; WorkQueue w;
+        if ((ws = workQueues) != null) {
+            for (int i = 1; i < ws.length; i += 2) {
+                if ((w = ws[i]) != null)
+                    count += w.queueSize();
+            }
         }
         return count;
     }
@@ -1750,7 +2875,15 @@
      * @return the number of queued submissions
      */
     public int getQueuedSubmissionCount() {
-        return -queueBase + queueTop;
+        int count = 0;
+        WorkQueue[] ws; WorkQueue w;
+        if ((ws = workQueues) != null) {
+            for (int i = 0; i < ws.length; i += 2) {
+                if ((w = ws[i]) != null)
+                    count += w.queueSize();
+            }
+        }
+        return count;
     }
 
     /**
@@ -1760,7 +2893,14 @@
      * @return {@code true} if there are any queued submissions
      */
     public boolean hasQueuedSubmissions() {
-        return queueBase != queueTop;
+        WorkQueue[] ws; WorkQueue w;
+        if ((ws = workQueues) != null) {
+            for (int i = 0; i < ws.length; i += 2) {
+                if ((w = ws[i]) != null && !w.isEmpty())
+                    return true;
+            }
+        }
+        return false;
     }
 
     /**
@@ -1771,16 +2911,11 @@
      * @return the next submission, or {@code null} if none
      */
     protected ForkJoinTask<?> pollSubmission() {
-        ForkJoinTask<?> t; ForkJoinTask<?>[] q; int b, i;
-        while ((b = queueBase) != queueTop &&
-               (q = submissionQueue) != null &&
-               (i = (q.length - 1) & b) >= 0) {
-            long u = (i << ASHIFT) + ABASE;
-            if ((t = q[i]) != null &&
-                queueBase == b &&
-                UNSAFE.compareAndSwapObject(q, u, t, null)) {
-                queueBase = b + 1;
-                return t;
+        WorkQueue[] ws; WorkQueue w; ForkJoinTask<?> t;
+        if ((ws = workQueues) != null) {
+            for (int i = 0; i < ws.length; i += 2) {
+                if ((w = ws[i]) != null && (t = w.poll()) != null)
+                    return t;
             }
         }
         return null;
@@ -1805,20 +2940,17 @@
      */
     protected int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
         int count = 0;
-        while (queueBase != queueTop) {
-            ForkJoinTask<?> t = pollSubmission();
-            if (t != null) {
-                c.add(t);
-                ++count;
+        WorkQueue[] ws; WorkQueue w; ForkJoinTask<?> t;
+        if ((ws = workQueues) != null) {
+            for (int i = 0; i < ws.length; ++i) {
+                if ((w = ws[i]) != null) {
+                    while ((t = w.poll()) != null) {
+                        c.add(t);
+                        ++count;
+                    }
+                }
             }
         }
-        ForkJoinWorkerThread[] ws;
-        if ((short)(ctl >>> TC_SHIFT) > -parallelism &&
-            (ws = workers) != null) {
-            for (ForkJoinWorkerThread w : ws)
-                if (w != null)
-                    count += w.drainTasksTo(c);
-        }
         return count;
     }
 
@@ -1830,21 +2962,36 @@
      * @return a string identifying this pool, as well as its state
      */
     public String toString() {
-        long st = getStealCount();
-        long qt = getQueuedTaskCount();
-        long qs = getQueuedSubmissionCount();
-        int pc = parallelism;
+        // Use a single pass through workQueues to collect counts
+        long qt = 0L, qs = 0L; int rc = 0;
+        long st = stealCount;
         long c = ctl;
+        WorkQueue[] ws; WorkQueue w;
+        if ((ws = workQueues) != null) {
+            for (int i = 0; i < ws.length; ++i) {
+                if ((w = ws[i]) != null) {
+                    int size = w.queueSize();
+                    if ((i & 1) == 0)
+                        qs += size;
+                    else {
+                        qt += size;
+                        st += w.nsteals;
+                        if (w.isApparentlyUnblocked())
+                            ++rc;
+                    }
+                }
+            }
+        }
+        int pc = (config & SMASK);
         int tc = pc + (short)(c >>> TC_SHIFT);
-        int rc = pc + (int)(c >> AC_SHIFT);
-        if (rc < 0) // ignore transient negative
-            rc = 0;
-        int ac = rc + blockedCount;
+        int ac = pc + (int)(c >> AC_SHIFT);
+        if (ac < 0) // ignore transient negative
+            ac = 0;
         String level;
         if ((c & STOP_BIT) != 0)
             level = (tc == 0) ? "Terminated" : "Terminating";
         else
-            level = shutdown ? "Shutting down" : "Running";
+            level = plock < 0 ? "Shutting down" : "Running";
         return super.toString() +
             "[" + level +
             ", parallelism = " + pc +
@@ -1858,34 +3005,41 @@
     }
 
     /**
-     * Initiates an orderly shutdown in which previously submitted
-     * tasks are executed, but no new tasks will be accepted.
-     * Invocation has no additional effect if already shut down.
-     * Tasks that are in the process of being submitted concurrently
-     * during the course of this method may or may not be rejected.
+     * Possibly initiates an orderly shutdown in which previously
+     * submitted tasks are executed, but no new tasks will be
+     * accepted. Invocation has no effect on execution state if this
+     * is the {@link #commonPool()}, and no additional effect if
+     * already shut down.  Tasks that are in the process of being
+     * submitted concurrently during the course of this method may or
+     * may not be rejected.
+     *
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
      */
     public void shutdown() {
         checkPermission();
-        shutdown = true;
-        tryTerminate(false);
+        tryTerminate(false, true);
     }
 
     /**
-     * Attempts to cancel and/or stop all tasks, and reject all
-     * subsequently submitted tasks.  Tasks that are in the process of
-     * being submitted or executed concurrently during the course of
-     * this method may or may not be rejected. This method cancels
-     * both existing and unexecuted tasks, in order to permit
-     * termination in the presence of task dependencies. So the method
-     * always returns an empty list (unlike the case for some other
-     * Executors).
+     * Possibly attempts to cancel and/or stop all tasks, and reject
+     * all subsequently submitted tasks.  Invocation has no effect on
+     * execution state if this is the {@link #commonPool()}, and no
+     * additional effect if already shut down. Otherwise, tasks that
+     * are in the process of being submitted or executed concurrently
+     * during the course of this method may or may not be
+     * rejected. This method cancels both existing and unexecuted
+     * tasks, in order to permit termination in the presence of task
+     * dependencies. So the method always returns an empty list
+     * (unlike the case for some other Executors).
      *
      * @return an empty list
      */
     public List<Runnable> shutdownNow() {
         checkPermission();
-        shutdown = true;
-        tryTerminate(true);
+        tryTerminate(true, true);
         return Collections.emptyList();
     }
 
@@ -1897,7 +3051,7 @@
     public boolean isTerminated() {
         long c = ctl;
         return ((c & STOP_BIT) != 0L &&
-                (short)(c >>> TC_SHIFT) == -parallelism);
+                (short)(c >>> TC_SHIFT) == -(config & SMASK));
     }
 
     /**
@@ -1905,7 +3059,7 @@
      * commenced but not yet completed.  This method may be useful for
      * debugging. A return of {@code true} reported a sufficient
      * period after shutdown may indicate that submitted tasks have
-     * ignored or suppressed interruption, or are waiting for IO,
+     * ignored or suppressed interruption, or are waiting for I/O,
      * causing this executor not to properly terminate. (See the
      * advisory notes for class {@link ForkJoinTask} stating that
      * tasks should not normally entail blocking operations.  But if
@@ -1916,14 +3070,7 @@
     public boolean isTerminating() {
         long c = ctl;
         return ((c & STOP_BIT) != 0L &&
-                (short)(c >>> TC_SHIFT) != -parallelism);
-    }
-
-    /**
-     * Returns true if terminating or terminated. Used by ForkJoinWorkerThread.
-     */
-    final boolean isAtLeastTerminating() {
-        return (ctl & STOP_BIT) != 0L;
+                (short)(c >>> TC_SHIFT) != -(config & SMASK));
     }
 
     /**
@@ -1932,13 +3079,15 @@
      * @return {@code true} if this pool has been shut down
      */
     public boolean isShutdown() {
-        return shutdown;
+        return plock < 0;
     }
 
     /**
-     * Blocks until all tasks have completed execution after a shutdown
-     * request, or the timeout occurs, or the current thread is
-     * interrupted, whichever happens first.
+     * Blocks until all tasks have completed execution after a
+     * shutdown request, or the timeout occurs, or the current thread
+     * is interrupted, whichever happens first. Note that the {@link
+     * #commonPool()} never terminates until program shutdown so
+     * this method will always time out.
      *
      * @param timeout the maximum time to wait
      * @param unit the time unit of the timeout argument
@@ -1949,18 +3098,21 @@
     public boolean awaitTermination(long timeout, TimeUnit unit)
         throws InterruptedException {
         long nanos = unit.toNanos(timeout);
-        final ReentrantLock lock = this.submissionLock;
-        lock.lock();
-        try {
+        if (isTerminated())
+            return true;
+        if (nanos <= 0L)
+            return false;
+        long deadline = System.nanoTime() + nanos;
+        synchronized (this) {
             for (;;) {
                 if (isTerminated())
                     return true;
-                if (nanos <= 0)
+                if (nanos <= 0L)
                     return false;
-                nanos = termination.awaitNanos(nanos);
+                long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
+                wait(millis > 0L ? millis : 1L);
+                nanos = deadline - System.nanoTime();
             }
-        } finally {
-            lock.unlock();
         }
     }
 
@@ -2061,11 +3213,35 @@
         throws InterruptedException {
         Thread t = Thread.currentThread();
         if (t instanceof ForkJoinWorkerThread) {
-            ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
-            w.pool.awaitBlocker(blocker);
+            ForkJoinPool p = ((ForkJoinWorkerThread)t).pool;
+            while (!blocker.isReleasable()) { // variant of helpSignal
+                WorkQueue[] ws; WorkQueue q; int m, u;
+                if ((ws = p.workQueues) != null && (m = ws.length - 1) >= 0) {
+                    for (int i = 0; i <= m; ++i) {
+                        if (blocker.isReleasable())
+                            return;
+                        if ((q = ws[i]) != null && q.base - q.top < 0) {
+                            p.signalWork(q);
+                            if ((u = (int)(p.ctl >>> 32)) >= 0 ||
+                                (u >> UAC_SHIFT) >= 0)
+                                break;
+                        }
+                    }
+                }
+                if (p.tryCompensate()) {
+                    try {
+                        do {} while (!blocker.isReleasable() &&
+                                     !blocker.block());
+                    } finally {
+                        p.incrementActiveCount();
+                    }
+                    break;
+                }
+            }
         }
         else {
-            do {} while (!blocker.isReleasable() && !blocker.block());
+            do {} while (!blocker.isReleasable() &&
+                         !blocker.block());
         }
     }
 
@@ -2074,54 +3250,93 @@
     // implement RunnableFuture.
 
     protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
-        return (RunnableFuture<T>) ForkJoinTask.adapt(runnable, value);
+        return new ForkJoinTask.AdaptedRunnable<T>(runnable, value);
     }
 
     protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
-        return (RunnableFuture<T>) ForkJoinTask.adapt(callable);
+        return new ForkJoinTask.AdaptedCallable<T>(callable);
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long ctlOffset;
-    private static final long stealCountOffset;
-    private static final long blockedCountOffset;
-    private static final long quiescerCountOffset;
-    private static final long scanGuardOffset;
-    private static final long nextWorkerNumberOffset;
-    private static final long ABASE;
+    private static final sun.misc.Unsafe U;
+    private static final long CTL;
+    private static final long PARKBLOCKER;
+    private static final int ABASE;
     private static final int ASHIFT;
+    private static final long STEALCOUNT;
+    private static final long PLOCK;
+    private static final long INDEXSEED;
+    private static final long QLOCK;
 
     static {
-        poolNumberGenerator = new AtomicInteger();
-        workerSeedGenerator = new Random();
-        modifyThreadPermission = new RuntimePermission("modifyThread");
-        defaultForkJoinWorkerThreadFactory =
-            new DefaultForkJoinWorkerThreadFactory();
+        // initialize field offsets for CAS etc
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
+            U = sun.misc.Unsafe.getUnsafe();
             Class<?> k = ForkJoinPool.class;
-            ctlOffset = UNSAFE.objectFieldOffset
+            CTL = U.objectFieldOffset
                 (k.getDeclaredField("ctl"));
-            stealCountOffset = UNSAFE.objectFieldOffset
+            STEALCOUNT = U.objectFieldOffset
                 (k.getDeclaredField("stealCount"));
-            blockedCountOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("blockedCount"));
-            quiescerCountOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("quiescerCount"));
-            scanGuardOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("scanGuard"));
-            nextWorkerNumberOffset = UNSAFE.objectFieldOffset
-                (k.getDeclaredField("nextWorkerNumber"));
+            PLOCK = U.objectFieldOffset
+                (k.getDeclaredField("plock"));
+            INDEXSEED = U.objectFieldOffset
+                (k.getDeclaredField("indexSeed"));
+            Class<?> tk = Thread.class;
+            PARKBLOCKER = U.objectFieldOffset
+                (tk.getDeclaredField("parkBlocker"));
+            Class<?> wk = WorkQueue.class;
+            QLOCK = U.objectFieldOffset
+                (wk.getDeclaredField("qlock"));
+            Class<?> ak = ForkJoinTask[].class;
+            ABASE = U.arrayBaseOffset(ak);
+            int scale = U.arrayIndexScale(ak);
+            if ((scale & (scale - 1)) != 0)
+                throw new Error("data type scale not a power of two");
+            ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
         } catch (Exception e) {
             throw new Error(e);
         }
-        Class<?> a = ForkJoinTask[].class;
-        ABASE = UNSAFE.arrayBaseOffset(a);
-        int s = UNSAFE.arrayIndexScale(a);
-        if ((s & (s-1)) != 0)
-            throw new Error("data type scale not a power of two");
-        ASHIFT = 31 - Integer.numberOfLeadingZeros(s);
+
+        submitters = new ThreadLocal<Submitter>();
+        ForkJoinWorkerThreadFactory fac = defaultForkJoinWorkerThreadFactory =
+            new DefaultForkJoinWorkerThreadFactory();
+        modifyThreadPermission = new RuntimePermission("modifyThread");
+
+        /*
+         * Establish common pool parameters.  For extra caution,
+         * computations to set up common pool state are here; the
+         * constructor just assigns these values to fields.
+         */
+
+        int par = 0;
+        Thread.UncaughtExceptionHandler handler = null;
+        try {  // TBD: limit or report ignored exceptions?
+            String pp = System.getProperty
+                ("java.util.concurrent.ForkJoinPool.common.parallelism");
+            String hp = System.getProperty
+                ("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
+            String fp = System.getProperty
+                ("java.util.concurrent.ForkJoinPool.common.threadFactory");
+            if (fp != null)
+                fac = ((ForkJoinWorkerThreadFactory)ClassLoader.
+                       getSystemClassLoader().loadClass(fp).newInstance());
+            if (hp != null)
+                handler = ((Thread.UncaughtExceptionHandler)ClassLoader.
+                           getSystemClassLoader().loadClass(hp).newInstance());
+            if (pp != null)
+                par = Integer.parseInt(pp);
+        } catch (Exception ignore) {
+        }
+
+        if (par <= 0)
+            par = Runtime.getRuntime().availableProcessors();
+        if (par > MAX_CAP)
+            par = MAX_CAP;
+        commonPoolParallelism = par;
+        long np = (long)(-par); // precompute initial ctl value
+        long ct = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
+
+        commonPool = new ForkJoinPool(par, ct, fac, handler);
     }
 
 }
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinTask.java b/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
index 86a29d7..818788e 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
@@ -22,7 +22,6 @@
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.locks.ReentrantLock;
 import java.lang.reflect.Constructor;
-import libcore.util.SneakyThrow;
 
 /**
  * Abstract base class for tasks that run within a {@link ForkJoinPool}.
@@ -31,46 +30,59 @@
  * subtasks may be hosted by a small number of actual threads in a
  * ForkJoinPool, at the price of some usage limitations.
  *
- * <p>A "main" {@code ForkJoinTask} begins execution when submitted
- * to a {@link ForkJoinPool}.  Once started, it will usually in turn
- * start other subtasks.  As indicated by the name of this class,
- * many programs using {@code ForkJoinTask} employ only methods
- * {@link #fork} and {@link #join}, or derivatives such as {@link
+ * <p>A "main" {@code ForkJoinTask} begins execution when it is
+ * explicitly submitted to a {@link ForkJoinPool}, or, if not already
+ * engaged in a ForkJoin computation, commenced in the {@link
+ * ForkJoinPool#commonPool()} via {@link #fork}, {@link #invoke}, or
+ * related methods.  Once started, it will usually in turn start other
+ * subtasks.  As indicated by the name of this class, many programs
+ * using {@code ForkJoinTask} employ only methods {@link #fork} and
+ * {@link #join}, or derivatives such as {@link
  * #invokeAll(ForkJoinTask...) invokeAll}.  However, this class also
  * provides a number of other methods that can come into play in
- * advanced usages, as well as extension mechanics that allow
- * support of new forms of fork/join processing.
+ * advanced usages, as well as extension mechanics that allow support
+ * of new forms of fork/join processing.
  *
  * <p>A {@code ForkJoinTask} is a lightweight form of {@link Future}.
  * The efficiency of {@code ForkJoinTask}s stems from a set of
  * restrictions (that are only partially statically enforceable)
- * reflecting their intended use as computational tasks calculating
- * pure functions or operating on purely isolated objects.  The
- * primary coordination mechanisms are {@link #fork}, that arranges
+ * reflecting their main use as computational tasks calculating pure
+ * functions or operating on purely isolated objects.  The primary
+ * coordination mechanisms are {@link #fork}, that arranges
  * asynchronous execution, and {@link #join}, that doesn't proceed
  * until the task's result has been computed.  Computations should
- * avoid {@code synchronized} methods or blocks, and should minimize
- * other blocking synchronization apart from joining other tasks or
- * using synchronizers such as Phasers that are advertised to
- * cooperate with fork/join scheduling. Tasks should also not perform
- * blocking IO, and should ideally access variables that are
- * completely independent of those accessed by other running
- * tasks. Minor breaches of these restrictions, for example using
- * shared output streams, may be tolerable in practice, but frequent
- * use may result in poor performance, and the potential to
- * indefinitely stall if the number of threads not waiting for IO or
- * other external synchronization becomes exhausted. This usage
- * restriction is in part enforced by not permitting checked
- * exceptions such as {@code IOExceptions} to be thrown. However,
- * computations may still encounter unchecked exceptions, that are
- * rethrown to callers attempting to join them. These exceptions may
- * additionally include {@link RejectedExecutionException} stemming
- * from internal resource exhaustion, such as failure to allocate
- * internal task queues. Rethrown exceptions behave in the same way as
- * regular exceptions, but, when possible, contain stack traces (as
- * displayed for example using {@code ex.printStackTrace()}) of both
- * the thread that initiated the computation as well as the thread
- * actually encountering the exception; minimally only the latter.
+ * ideally avoid {@code synchronized} methods or blocks, and should
+ * minimize other blocking synchronization apart from joining other
+ * tasks or using synchronizers such as Phasers that are advertised to
+ * cooperate with fork/join scheduling. Subdividable tasks should also
+ * not perform blocking I/O, and should ideally access variables that
+ * are completely independent of those accessed by other running
+ * tasks. These guidelines are loosely enforced by not permitting
+ * checked exceptions such as {@code IOExceptions} to be
+ * thrown. However, computations may still encounter unchecked
+ * exceptions, that are rethrown to callers attempting to join
+ * them. These exceptions may additionally include {@link
+ * RejectedExecutionException} stemming from internal resource
+ * exhaustion, such as failure to allocate internal task
+ * queues. Rethrown exceptions behave in the same way as regular
+ * exceptions, but, when possible, contain stack traces (as displayed
+ * for example using {@code ex.printStackTrace()}) of both the thread
+ * that initiated the computation as well as the thread actually
+ * encountering the exception; minimally only the latter.
+ *
+ * <p>It is possible to define and use ForkJoinTasks that may block,
+ * but doing do requires three further considerations: (1) Completion
+ * of few if any <em>other</em> tasks should be dependent on a task
+ * that blocks on external synchronization or I/O. Event-style async
+ * tasks that are never joined (for example, those subclassing {@link
+ * CountedCompleter}) often fall into this category.  (2) To minimize
+ * resource impact, tasks should be small; ideally performing only the
+ * (possibly) blocking action. (3) Unless the {@link
+ * ForkJoinPool.ManagedBlocker} API is used, or the number of possibly
+ * blocked tasks is known to be less than the pool's {@link
+ * ForkJoinPool#getParallelism} level, the pool cannot guarantee that
+ * enough threads will be available to ensure progress or good
+ * performance.
  *
  * <p>The primary method for awaiting completion and extracting
  * results of a task is {@link #join}, but there are several variants:
@@ -86,6 +98,13 @@
  * performs the most common form of parallel invocation: forking a set
  * of tasks and joining them all.
  *
+ * <p>In the most typical usages, a fork-join pair act like a call
+ * (fork) and return (join) from a parallel recursive function. As is
+ * the case with other forms of recursive calls, returns (joins)
+ * should be performed innermost-first. For example, {@code a.fork();
+ * b.fork(); b.join(); a.join();} is likely to be substantially more
+ * efficient than joining {@code a} before {@code b}.
+ *
  * <p>The execution status of tasks may be queried at several levels
  * of detail: {@link #isDone} is true if a task completed in any way
  * (including the case where a task was cancelled without executing);
@@ -101,18 +120,13 @@
  * <p>The ForkJoinTask class is not usually directly subclassed.
  * Instead, you subclass one of the abstract classes that support a
  * particular style of fork/join processing, typically {@link
- * RecursiveAction} for computations that do not return results, or
- * {@link RecursiveTask} for those that do.  Normally, a concrete
- * ForkJoinTask subclass declares fields comprising its parameters,
- * established in a constructor, and then defines a {@code compute}
- * method that somehow uses the control methods supplied by this base
- * class. While these methods have {@code public} access (to allow
- * instances of different task subclasses to call each other's
- * methods), some of them may only be called from within other
- * ForkJoinTasks (as may be determined using method {@link
- * #inForkJoinPool}).  Attempts to invoke them in other contexts
- * result in exceptions or errors, possibly including
- * {@code ClassCastException}.
+ * RecursiveAction} for most computations that do not return results,
+ * {@link RecursiveTask} for those that do, and {@link
+ * CountedCompleter} for those in which completed actions trigger
+ * other actions.  Normally, a concrete ForkJoinTask subclass declares
+ * fields comprising its parameters, established in a constructor, and
+ * then defines a {@code compute} method that somehow uses the control
+ * methods supplied by this base class.
  *
  * <p>Method {@link #join} and its variants are appropriate for use
  * only when completion dependencies are acyclic; that is, the
@@ -122,7 +136,17 @@
  * supports other methods and techniques (for example the use of
  * {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that
  * may be of use in constructing custom subclasses for problems that
- * are not statically structured as DAGs.
+ * are not statically structured as DAGs. To support such usages a
+ * ForkJoinTask may be atomically <em>tagged</em> with a {@code short}
+ * value using {@link #setForkJoinTaskTag} or {@link
+ * #compareAndSetForkJoinTaskTag} and checked using {@link
+ * #getForkJoinTaskTag}. The ForkJoinTask implementation does not use
+ * these {@code protected} methods or tags for any purpose, but they
+ * may be of use in the construction of specialized subclasses.  For
+ * example, parallel graph traversals can use the supplied methods to
+ * avoid revisiting nodes/tasks that have already been processed.
+ * (Method names for tagging are bulky in part to encourage definition
+ * of methods that reflect their usage patterns.)
  *
  * <p>Most base support methods are {@code final}, to prevent
  * overriding of implementations that are intrinsically tied to the
@@ -177,29 +201,36 @@
      * The status field holds run control status bits packed into a
      * single int to minimize footprint and to ensure atomicity (via
      * CAS).  Status is initially zero, and takes on nonnegative
-     * values until completed, upon which status holds value
-     * NORMAL, CANCELLED, or EXCEPTIONAL. Tasks undergoing blocking
-     * waits by other threads have the SIGNAL bit set.  Completion of
-     * a stolen task with SIGNAL set awakens any waiters via
-     * notifyAll. Even though suboptimal for some purposes, we use
-     * basic builtin wait/notify to take advantage of "monitor
-     * inflation" in JVMs that we would otherwise need to emulate to
-     * avoid adding further per-task bookkeeping overhead.  We want
-     * these monitors to be "fat", i.e., not use biasing or thin-lock
-     * techniques, so use some odd coding idioms that tend to avoid
-     * them.
+     * values until completed, upon which status (anded with
+     * DONE_MASK) holds value NORMAL, CANCELLED, or EXCEPTIONAL. Tasks
+     * undergoing blocking waits by other threads have the SIGNAL bit
+     * set.  Completion of a stolen task with SIGNAL set awakens any
+     * waiters via notifyAll. Even though suboptimal for some
+     * purposes, we use basic builtin wait/notify to take advantage of
+     * "monitor inflation" in JVMs that we would otherwise need to
+     * emulate to avoid adding further per-task bookkeeping overhead.
+     * We want these monitors to be "fat", i.e., not use biasing or
+     * thin-lock techniques, so use some odd coding idioms that tend
+     * to avoid them, mainly by arranging that every synchronized
+     * block performs a wait, notifyAll or both.
+     *
+     * These control bits occupy only (some of) the upper half (16
+     * bits) of status field. The lower bits are used for user-defined
+     * tags.
      */
 
     /** The run status of this task */
     volatile int status; // accessed directly by pool and workers
-    private static final int NORMAL      = -1;
-    private static final int CANCELLED   = -2;
-    private static final int EXCEPTIONAL = -3;
-    private static final int SIGNAL      =  1;
+    static final int DONE_MASK   = 0xf0000000;  // mask out non-completion bits
+    static final int NORMAL      = 0xf0000000;  // must be negative
+    static final int CANCELLED   = 0xc0000000;  // must be < NORMAL
+    static final int EXCEPTIONAL = 0x80000000;  // must be < CANCELLED
+    static final int SIGNAL      = 0x00010000;  // must be >= 1 << 16
+    static final int SMASK       = 0x0000ffff;  // short bits for tags
 
     /**
-     * Marks completion and wakes up threads waiting to join this task,
-     * also clearing signal request bits.
+     * Marks completion and wakes up threads waiting to join this
+     * task.
      *
      * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
      * @return completion status on exit
@@ -208,8 +239,8 @@
         for (int s;;) {
             if ((s = status) < 0)
                 return s;
-            if (UNSAFE.compareAndSwapInt(this, statusOffset, s, completion)) {
-                if (s != 0)
+            if (U.compareAndSwapInt(this, STATUS, s, s | completion)) {
+                if ((s >>> 16) != 0)
                     synchronized (this) { notifyAll(); }
                 return completion;
             }
@@ -217,27 +248,36 @@
     }
 
     /**
-     * Tries to block a worker thread until completed or timed out.
-     * Uses Object.wait time argument conventions.
-     * May fail on contention or interrupt.
+     * Primary execution method for stolen tasks. Unless done, calls
+     * exec and records status if completed, but doesn't wait for
+     * completion otherwise.
      *
-     * @param millis if > 0, wait time.
+     * @return status on exit from this method
      */
-    final void tryAwaitDone(long millis) {
-        int s;
-        try {
-            if (((s = status) > 0 ||
-                 (s == 0 &&
-                  UNSAFE.compareAndSwapInt(this, statusOffset, 0, SIGNAL))) &&
-                status > 0) {
-                synchronized (this) {
-                    if (status > 0)
-                        wait(millis);
-                }
+    final int doExec() {
+        int s; boolean completed;
+        if ((s = status) >= 0) {
+            try {
+                completed = exec();
+            } catch (Throwable rex) {
+                return setExceptionalCompletion(rex);
             }
-        } catch (InterruptedException ie) {
-            // caller must check termination
+            if (completed)
+                s = setCompletion(NORMAL);
         }
+        return s;
+    }
+
+    /**
+     * Tries to set SIGNAL status unless already completed. Used by
+     * ForkJoinPool. Other variants are directly incorporated into
+     * externalAwaitDone etc.
+     *
+     * @return true if successful
+     */
+    final boolean trySetSignal() {
+        int s = status;
+        return s >= 0 && U.compareAndSwapInt(this, STATUS, s, s | SIGNAL);
     }
 
     /**
@@ -246,113 +286,78 @@
      */
     private int externalAwaitDone() {
         int s;
-        if ((s = status) >= 0) {
-            boolean interrupted = false;
-            synchronized (this) {
-                while ((s = status) >= 0) {
-                    if (s == 0)
-                        UNSAFE.compareAndSwapInt(this, statusOffset,
-                                                 0, SIGNAL);
-                    else {
+        ForkJoinPool.externalHelpJoin(this);
+        boolean interrupted = false;
+        while ((s = status) >= 0) {
+            if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                synchronized (this) {
+                    if (status >= 0) {
                         try {
                             wait();
                         } catch (InterruptedException ie) {
                             interrupted = true;
                         }
                     }
+                    else
+                        notifyAll();
                 }
             }
-            if (interrupted)
-                Thread.currentThread().interrupt();
         }
+        if (interrupted)
+            Thread.currentThread().interrupt();
         return s;
     }
 
     /**
-     * Blocks a non-worker-thread until completion or interruption or timeout.
+     * Blocks a non-worker-thread until completion or interruption.
      */
-    private int externalInterruptibleAwaitDone(long millis)
-        throws InterruptedException {
+    private int externalInterruptibleAwaitDone() throws InterruptedException {
         int s;
         if (Thread.interrupted())
             throw new InterruptedException();
-        if ((s = status) >= 0) {
-            synchronized (this) {
-                while ((s = status) >= 0) {
-                    if (s == 0)
-                        UNSAFE.compareAndSwapInt(this, statusOffset,
-                                                 0, SIGNAL);
-                    else {
-                        wait(millis);
-                        if (millis > 0L)
-                            break;
-                    }
+        ForkJoinPool.externalHelpJoin(this);
+        while ((s = status) >= 0) {
+            if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                synchronized (this) {
+                    if (status >= 0)
+                        wait();
+                    else
+                        notifyAll();
                 }
             }
         }
         return s;
     }
 
-    /**
-     * Primary execution method for stolen tasks. Unless done, calls
-     * exec and records status if completed, but doesn't wait for
-     * completion otherwise.
-     */
-    final void doExec() {
-        if (status >= 0) {
-            boolean completed;
-            try {
-                completed = exec();
-            } catch (Throwable rex) {
-                setExceptionalCompletion(rex);
-                return;
-            }
-            if (completed)
-                setCompletion(NORMAL); // must be outside try block
-        }
-    }
 
     /**
-     * Primary mechanics for join, get, quietlyJoin.
+     * Implementation for join, get, quietlyJoin. Directly handles
+     * only cases of already-completed, external wait, and
+     * unfork+exec.  Others are relayed to ForkJoinPool.awaitJoin.
+     *
      * @return status upon completion
      */
     private int doJoin() {
-        Thread t; ForkJoinWorkerThread w; int s; boolean completed;
-        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
-            if ((s = status) < 0)
-                return s;
-            if ((w = (ForkJoinWorkerThread)t).unpushTask(this)) {
-                try {
-                    completed = exec();
-                } catch (Throwable rex) {
-                    return setExceptionalCompletion(rex);
-                }
-                if (completed)
-                    return setCompletion(NORMAL);
-            }
-            return w.joinTask(this);
-        }
-        else
-            return externalAwaitDone();
+        int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;
+        return (s = status) < 0 ? s :
+            ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+            (w = (wt = (ForkJoinWorkerThread)t).workQueue).
+            tryUnpush(this) && (s = doExec()) < 0 ? s :
+            wt.pool.awaitJoin(w, this) :
+            externalAwaitDone();
     }
 
     /**
-     * Primary mechanics for invoke, quietlyInvoke.
+     * Implementation for invoke, quietlyInvoke.
+     *
      * @return status upon completion
      */
     private int doInvoke() {
-        int s; boolean completed;
-        if ((s = status) < 0)
-            return s;
-        try {
-            completed = exec();
-        } catch (Throwable rex) {
-            return setExceptionalCompletion(rex);
-        }
-        if (completed)
-            return setCompletion(NORMAL);
-        else
-            return doJoin();
+        int s; Thread t; ForkJoinWorkerThread wt;
+        return (s = doExec()) < 0 ? s :
+            ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+            (wt = (ForkJoinWorkerThread)t).pool.awaitJoin(wt.workQueue, this) :
+            externalAwaitDone();
     }
 
     // Exception table support
@@ -387,7 +392,7 @@
      * any ForkJoinPool will call helpExpungeStaleExceptions when its
      * pool becomes isQuiescent.
      */
-    static final class ExceptionNode extends WeakReference<ForkJoinTask<?>>{
+    static final class ExceptionNode extends WeakReference<ForkJoinTask<?>> {
         final Throwable ex;
         ExceptionNode next;
         final long thrower;  // use id not ref to avoid weak cycles
@@ -400,34 +405,71 @@
     }
 
     /**
-     * Records exception and sets exceptional completion.
+     * Records exception and sets status.
+     *
+     * @return status on exit
+     */
+    final int recordExceptionalCompletion(Throwable ex) {
+        int s;
+        if ((s = status) >= 0) {
+            int h = System.identityHashCode(this);
+            final ReentrantLock lock = exceptionTableLock;
+            lock.lock();
+            try {
+                expungeStaleExceptions();
+                ExceptionNode[] t = exceptionTable;
+                int i = h & (t.length - 1);
+                for (ExceptionNode e = t[i]; ; e = e.next) {
+                    if (e == null) {
+                        t[i] = new ExceptionNode(this, ex, t[i]);
+                        break;
+                    }
+                    if (e.get() == this) // already present
+                        break;
+                }
+            } finally {
+                lock.unlock();
+            }
+            s = setCompletion(EXCEPTIONAL);
+        }
+        return s;
+    }
+
+    /**
+     * Records exception and possibly propagates.
      *
      * @return status on exit
      */
     private int setExceptionalCompletion(Throwable ex) {
-        int h = System.identityHashCode(this);
-        final ReentrantLock lock = exceptionTableLock;
-        lock.lock();
-        try {
-            expungeStaleExceptions();
-            ExceptionNode[] t = exceptionTable;
-            int i = h & (t.length - 1);
-            for (ExceptionNode e = t[i]; ; e = e.next) {
-                if (e == null) {
-                    t[i] = new ExceptionNode(this, ex, t[i]);
-                    break;
-                }
-                if (e.get() == this) // already present
-                    break;
-            }
-        } finally {
-            lock.unlock();
-        }
-        return setCompletion(EXCEPTIONAL);
+        int s = recordExceptionalCompletion(ex);
+        if ((s & DONE_MASK) == EXCEPTIONAL)
+            internalPropagateException(ex);
+        return s;
     }
 
     /**
-     * Removes exception node and clears status
+     * Hook for exception propagation support for tasks with completers.
+     */
+    void internalPropagateException(Throwable ex) {
+    }
+
+    /**
+     * Cancels, ignoring any exceptions thrown by cancel. Used during
+     * worker and pool shutdown. Cancel is spec'ed not to throw any
+     * exceptions, but if it does anyway, we have no recourse during
+     * shutdown, so guard against this case.
+     */
+    static final void cancelIgnoringExceptions(ForkJoinTask<?> t) {
+        if (t != null && t.status >= 0) {
+            try {
+                t.cancel(false);
+            } catch (Throwable ignore) {
+            }
+        }
+    }
+
+    /**
+     * Removes exception node and clears status.
      */
     private void clearExceptionalCompletion() {
         int h = System.identityHashCode(this);
@@ -472,7 +514,7 @@
      * @return the exception, or null if none
      */
     private Throwable getThrowableException() {
-        if (status != EXCEPTIONAL)
+        if ((status & DONE_MASK) != EXCEPTIONAL)
             return null;
         int h = System.identityHashCode(this);
         ExceptionNode e;
@@ -490,7 +532,7 @@
         Throwable ex;
         if (e == null || (ex = e.ex) == null)
             return null;
-        if (e.thrower != Thread.currentThread().getId()) {
+        if (false && e.thrower != Thread.currentThread().getId()) {
             Class<? extends Throwable> ec = ex.getClass();
             try {
                 Constructor<?> noArgCtor = null;
@@ -557,41 +599,61 @@
     }
 
     /**
-     * Report the result of invoke or join; called only upon
-     * non-normal return of internal versions.
+     * A version of "sneaky throw" to relay exceptions
      */
-    private V reportResult() {
-        int s; Throwable ex;
-        if ((s = status) == CANCELLED)
+    static void rethrow(final Throwable ex) {
+        if (ex != null) {
+            if (ex instanceof Error)
+                throw (Error)ex;
+            if (ex instanceof RuntimeException)
+                throw (RuntimeException)ex;
+            throw uncheckedThrowable(ex, RuntimeException.class);
+        }
+    }
+
+    /**
+     * The sneaky part of sneaky throw, relying on generics
+     * limitations to evade compiler complaints about rethrowing
+     * unchecked exceptions
+     */
+    @SuppressWarnings("unchecked") static <T extends Throwable>
+        T uncheckedThrowable(final Throwable t, final Class<T> c) {
+        return (T)t; // rely on vacuous cast
+    }
+
+    /**
+     * Throws exception, if any, associated with the given status.
+     */
+    private void reportException(int s) {
+        if (s == CANCELLED)
             throw new CancellationException();
-        if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
-            SneakyThrow.sneakyThrow(ex); // android-changed
-        return getRawResult();
+        if (s == EXCEPTIONAL)
+            rethrow(getThrowableException());
     }
 
     // public methods
 
     /**
-     * Arranges to asynchronously execute this task.  While it is not
-     * necessarily enforced, it is a usage error to fork a task more
-     * than once unless it has completed and been reinitialized.
-     * Subsequent modifications to the state of this task or any data
-     * it operates on are not necessarily consistently observable by
-     * any thread other than the one executing it unless preceded by a
-     * call to {@link #join} or related methods, or a call to {@link
-     * #isDone} returning {@code true}.
-     *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
+     * Arranges to asynchronously execute this task in the pool the
+     * current task is running in, if applicable, or using the {@link
+     * ForkJoinPool#commonPool()} if not {@link #inForkJoinPool}.  While
+     * it is not necessarily enforced, it is a usage error to fork a
+     * task more than once unless it has completed and been
+     * reinitialized.  Subsequent modifications to the state of this
+     * task or any data it operates on are not necessarily
+     * consistently observable by any thread other than the one
+     * executing it unless preceded by a call to {@link #join} or
+     * related methods, or a call to {@link #isDone} returning {@code
+     * true}.
      *
      * @return {@code this}, to simplify usage
      */
     public final ForkJoinTask<V> fork() {
-        ((ForkJoinWorkerThread) Thread.currentThread())
-            .pushTask(this);
+        Thread t;
+        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
+            ((ForkJoinWorkerThread)t).workQueue.push(this);
+        else
+            ForkJoinPool.commonPool.externalPush(this);
         return this;
     }
 
@@ -607,10 +669,10 @@
      * @return the computed result
      */
     public final V join() {
-        if (doJoin() != NORMAL)
-            return reportResult();
-        else
-            return getRawResult();
+        int s;
+        if ((s = doJoin() & DONE_MASK) != NORMAL)
+            reportException(s);
+        return getRawResult();
     }
 
     /**
@@ -622,10 +684,10 @@
      * @return the computed result
      */
     public final V invoke() {
-        if (doInvoke() != NORMAL)
-            return reportResult();
-        else
-            return getRawResult();
+        int s;
+        if ((s = doInvoke() & DONE_MASK) != NORMAL)
+            reportException(s);
+        return getRawResult();
     }
 
     /**
@@ -641,20 +703,17 @@
      * cancelled, completed normally or exceptionally, or left
      * unprocessed.
      *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
-     *
      * @param t1 the first task
      * @param t2 the second task
      * @throws NullPointerException if any task is null
      */
     public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) {
+        int s1, s2;
         t2.fork();
-        t1.invoke();
-        t2.join();
+        if ((s1 = t1.doInvoke() & DONE_MASK) != NORMAL)
+            t1.reportException(s1);
+        if ((s2 = t2.doJoin() & DONE_MASK) != NORMAL)
+            t2.reportException(s2);
     }
 
     /**
@@ -669,12 +728,6 @@
      * related methods to check if they have been cancelled, completed
      * normally or exceptionally, or left unprocessed.
      *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
-     *
      * @param tasks the tasks
      * @throws NullPointerException if any task is null
      */
@@ -702,7 +755,7 @@
             }
         }
         if (ex != null)
-            SneakyThrow.sneakyThrow(ex); // android-changed
+            rethrow(ex);
     }
 
     /**
@@ -718,15 +771,11 @@
      * cancelled, completed normally or exceptionally, or left
      * unprocessed.
      *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
-     *
      * @param tasks the collection of tasks
      * @return the tasks argument, to simplify usage
      * @throws NullPointerException if tasks or any element are null
+
+     * @hide
      */
     public static <T extends ForkJoinTask<?>> Collection<T> invokeAll(Collection<T> tasks) {
         if (!(tasks instanceof RandomAccess) || !(tasks instanceof List<?>)) {
@@ -759,7 +808,7 @@
             }
         }
         if (ex != null)
-            SneakyThrow.sneakyThrow(ex); // android-changed
+            rethrow(ex);
         return tasks;
     }
 
@@ -791,20 +840,7 @@
      * @return {@code true} if this task is now cancelled
      */
     public boolean cancel(boolean mayInterruptIfRunning) {
-        return setCompletion(CANCELLED) == CANCELLED;
-    }
-
-    /**
-     * Cancels, ignoring any exceptions thrown by cancel. Used during
-     * worker and pool shutdown. Cancel is spec'ed not to throw any
-     * exceptions, but if it does anyway, we have no recourse during
-     * shutdown, so guard against this case.
-     */
-    final void cancelIgnoringExceptions() {
-        try {
-            cancel(false);
-        } catch (Throwable ignore) {
-        }
+        return (setCompletion(CANCELLED) & DONE_MASK) == CANCELLED;
     }
 
     public final boolean isDone() {
@@ -812,7 +848,7 @@
     }
 
     public final boolean isCancelled() {
-        return status == CANCELLED;
+        return (status & DONE_MASK) == CANCELLED;
     }
 
     /**
@@ -832,7 +868,7 @@
      * exception and was not cancelled
      */
     public final boolean isCompletedNormally() {
-        return status == NORMAL;
+        return (status & DONE_MASK) == NORMAL;
     }
 
     /**
@@ -843,7 +879,7 @@
      * @return the exception, or {@code null} if none
      */
     public final Throwable getException() {
-        int s = status;
+        int s = status & DONE_MASK;
         return ((s >= NORMAL)    ? null :
                 (s == CANCELLED) ? new CancellationException() :
                 getThrowableException());
@@ -893,6 +929,19 @@
     }
 
     /**
+     * Completes this task normally without setting a value. The most
+     * recent value established by {@link #setRawResult} (or {@code
+     * null} by default) will be returned as the result of subsequent
+     * invocations of {@code join} and related operations.
+     *
+     * @since 1.8
+     * @hide
+     */
+    public final void quietlyComplete() {
+        setCompletion(NORMAL);
+    }
+
+    /**
      * Waits if necessary for the computation to complete, and then
      * retrieves its result.
      *
@@ -905,9 +954,9 @@
      */
     public final V get() throws InterruptedException, ExecutionException {
         int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ?
-            doJoin() : externalInterruptibleAwaitDone(0L);
+            doJoin() : externalInterruptibleAwaitDone();
         Throwable ex;
-        if (s == CANCELLED)
+        if ((s &= DONE_MASK) == CANCELLED)
             throw new CancellationException();
         if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
             throw new ExecutionException(ex);
@@ -930,32 +979,63 @@
      */
     public final V get(long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException {
-        Thread t = Thread.currentThread();
-        if (t instanceof ForkJoinWorkerThread) {
-            ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
-            long nanos = unit.toNanos(timeout);
-            if (status >= 0) {
-                boolean completed = false;
-                if (w.unpushTask(this)) {
-                    try {
-                        completed = exec();
-                    } catch (Throwable rex) {
-                        setExceptionalCompletion(rex);
+        if (Thread.interrupted())
+            throw new InterruptedException();
+        // Messy in part because we measure in nanosecs, but wait in millisecs
+        int s; long ms;
+        long ns = unit.toNanos(timeout);
+        if ((s = status) >= 0 && ns > 0L) {
+            long deadline = System.nanoTime() + ns;
+            ForkJoinPool p = null;
+            ForkJoinPool.WorkQueue w = null;
+            Thread t = Thread.currentThread();
+            if (t instanceof ForkJoinWorkerThread) {
+                ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t;
+                p = wt.pool;
+                w = wt.workQueue;
+                p.helpJoinOnce(w, this); // no retries on failure
+            }
+            else
+                ForkJoinPool.externalHelpJoin(this);
+            boolean canBlock = false;
+            boolean interrupted = false;
+            try {
+                while ((s = status) >= 0) {
+                    if (w != null && w.qlock < 0)
+                        cancelIgnoringExceptions(this);
+                    else if (!canBlock) {
+                        if (p == null || p.tryCompensate())
+                            canBlock = true;
+                    }
+                    else {
+                        if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L &&
+                            U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                            synchronized (this) {
+                                if (status >= 0) {
+                                    try {
+                                        wait(ms);
+                                    } catch (InterruptedException ie) {
+                                        if (p == null)
+                                            interrupted = true;
+                                    }
+                                }
+                                else
+                                    notifyAll();
+                            }
+                        }
+                        if ((s = status) < 0 || interrupted ||
+                            (ns = deadline - System.nanoTime()) <= 0L)
+                            break;
                     }
                 }
-                if (completed)
-                    setCompletion(NORMAL);
-                else if (status >= 0 && nanos > 0)
-                    w.pool.timedAwaitJoin(this, nanos);
+            } finally {
+                if (p != null && canBlock)
+                    p.incrementActiveCount();
             }
+            if (interrupted)
+                throw new InterruptedException();
         }
-        else {
-            long millis = unit.toMillis(timeout);
-            if (millis > 0)
-                externalInterruptibleAwaitDone(millis);
-        }
-        int s = status;
-        if (s != NORMAL) {
+        if ((s &= DONE_MASK) != NORMAL) {
             Throwable ex;
             if (s == CANCELLED)
                 throw new CancellationException();
@@ -992,16 +1072,15 @@
      * be of use in designs in which many tasks are forked, but none
      * are explicitly joined, instead executing them until all are
      * processed.
-     *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
      */
     public static void helpQuiesce() {
-        ((ForkJoinWorkerThread) Thread.currentThread())
-            .helpQuiescePool();
+        Thread t;
+        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
+            ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t;
+            wt.pool.helpQuiescePool(wt.workQueue);
+        }
+        else
+            ForkJoinPool.externalHelpQuiescePool();
     }
 
     /**
@@ -1021,7 +1100,7 @@
      * setRawResult(null)}.
      */
     public void reinitialize() {
-        if (status == EXCEPTIONAL)
+        if ((status & DONE_MASK) == EXCEPTIONAL)
             clearExceptionalCompletion();
         else
             status = 0;
@@ -1054,23 +1133,19 @@
 
     /**
      * Tries to unschedule this task for execution. This method will
-     * typically succeed if this task is the most recently forked task
-     * by the current thread, and has not commenced executing in
-     * another thread.  This method may be useful when arranging
-     * alternative local processing of tasks that could have been, but
-     * were not, stolen.
-     *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
+     * typically (but is not guaranteed to) succeed if this task is
+     * the most recently forked task by the current thread, and has
+     * not commenced executing in another thread.  This method may be
+     * useful when arranging alternative local processing of tasks
+     * that could have been, but were not, stolen.
      *
      * @return {@code true} if unforked
      */
     public boolean tryUnfork() {
-        return ((ForkJoinWorkerThread) Thread.currentThread())
-            .unpushTask(this);
+        Thread t;
+        return (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+                ((ForkJoinWorkerThread)t).workQueue.tryUnpush(this) :
+                ForkJoinPool.tryExternalUnpush(this));
     }
 
     /**
@@ -1079,40 +1154,32 @@
      * value may be useful for heuristic decisions about whether to
      * fork other tasks.
      *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
-     *
      * @return the number of tasks
      */
     public static int getQueuedTaskCount() {
-        return ((ForkJoinWorkerThread) Thread.currentThread())
-            .getQueueSize();
+        Thread t; ForkJoinPool.WorkQueue q;
+        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
+            q = ((ForkJoinWorkerThread)t).workQueue;
+        else
+            q = ForkJoinPool.commonSubmitterQueue();
+        return (q == null) ? 0 : q.queueSize();
     }
 
     /**
      * Returns an estimate of how many more locally queued tasks are
      * held by the current worker thread than there are other worker
-     * threads that might steal them.  This value may be useful for
+     * threads that might steal them, or zero if this thread is not
+     * operating in a ForkJoinPool. This value may be useful for
      * heuristic decisions about whether to fork other tasks. In many
      * usages of ForkJoinTasks, at steady state, each worker should
      * aim to maintain a small constant surplus (for example, 3) of
      * tasks, and to process computations locally if this threshold is
      * exceeded.
      *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
-     *
      * @return the surplus number of tasks, which may be negative
      */
     public static int getSurplusQueuedTaskCount() {
-        return ((ForkJoinWorkerThread) Thread.currentThread())
-            .getEstimatedSurplusTaskCount();
+        return ForkJoinPool.getSurplusQueuedTaskCount();
     }
 
     // Extension methods
@@ -1138,15 +1205,18 @@
     protected abstract void setRawResult(V value);
 
     /**
-     * Immediately performs the base action of this task.  This method
-     * is designed to support extensions, and should not in general be
-     * called otherwise. The return value controls whether this task
-     * is considered to be done normally. It may return false in
+     * Immediately performs the base action of this task and returns
+     * true if, upon return from this method, this task is guaranteed
+     * to have completed normally. This method may return false
+     * otherwise, to indicate that this task is not necessarily
+     * complete (or is not known to be complete), for example in
      * asynchronous actions that require explicit invocations of
-     * {@link #complete} to become joinable. It may also throw an
-     * (unchecked) exception to indicate abnormal exit.
+     * completion methods. This method may also throw an (unchecked)
+     * exception to indicate abnormal exit. This method is designed to
+     * support extensions, and should not in general be called
+     * otherwise.
      *
-     * @return {@code true} if completed normally
+     * @return {@code true} if this task is known to have completed normally
      */
     protected abstract boolean exec();
 
@@ -1160,59 +1230,105 @@
      * primarily to support extensions, and is unlikely to be useful
      * otherwise.
      *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
-     *
      * @return the next task, or {@code null} if none are available
      */
     protected static ForkJoinTask<?> peekNextLocalTask() {
-        return ((ForkJoinWorkerThread) Thread.currentThread())
-            .peekTask();
+        Thread t; ForkJoinPool.WorkQueue q;
+        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
+            q = ((ForkJoinWorkerThread)t).workQueue;
+        else
+            q = ForkJoinPool.commonSubmitterQueue();
+        return (q == null) ? null : q.peek();
     }
 
     /**
      * Unschedules and returns, without executing, the next task
-     * queued by the current thread but not yet executed.  This method
-     * is designed primarily to support extensions, and is unlikely to
-     * be useful otherwise.
-     *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
+     * queued by the current thread but not yet executed, if the
+     * current thread is operating in a ForkJoinPool.  This method is
+     * designed primarily to support extensions, and is unlikely to be
+     * useful otherwise.
      *
      * @return the next task, or {@code null} if none are available
      */
     protected static ForkJoinTask<?> pollNextLocalTask() {
-        return ((ForkJoinWorkerThread) Thread.currentThread())
-            .pollLocalTask();
+        Thread t;
+        return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+            ((ForkJoinWorkerThread)t).workQueue.nextLocalTask() :
+            null;
     }
 
     /**
-     * Unschedules and returns, without executing, the next task
+     * If the current thread is operating in a ForkJoinPool,
+     * unschedules and returns, without executing, the next task
      * queued by the current thread but not yet executed, if one is
      * available, or if not available, a task that was forked by some
      * other thread, if available. Availability may be transient, so a
-     * {@code null} result does not necessarily imply quiescence
-     * of the pool this task is operating in.  This method is designed
+     * {@code null} result does not necessarily imply quiescence of
+     * the pool this task is operating in.  This method is designed
      * primarily to support extensions, and is unlikely to be useful
      * otherwise.
      *
-     * <p>This method may be invoked only from within {@code
-     * ForkJoinPool} computations (as may be determined using method
-     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
-     * result in exceptions or errors, possibly including {@code
-     * ClassCastException}.
-     *
      * @return a task, or {@code null} if none are available
      */
     protected static ForkJoinTask<?> pollTask() {
-        return ((ForkJoinWorkerThread) Thread.currentThread())
-            .pollTask();
+        Thread t; ForkJoinWorkerThread wt;
+        return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+            (wt = (ForkJoinWorkerThread)t).pool.nextTaskFor(wt.workQueue) :
+            null;
+    }
+
+    // tag operations
+
+    /**
+     * Returns the tag for this task.
+     *
+     * @return the tag for this task
+     * @since 1.8
+     * @hide
+     */
+    public final short getForkJoinTaskTag() {
+        return (short)status;
+    }
+
+    /**
+     * Atomically sets the tag value for this task.
+     *
+     * @param tag the tag value
+     * @return the previous value of the tag
+     * @since 1.8
+     * @hide
+     */
+    public final short setForkJoinTaskTag(short tag) {
+        for (int s;;) {
+            if (U.compareAndSwapInt(this, STATUS, s = status,
+                                    (s & ~SMASK) | (tag & SMASK)))
+                return (short)s;
+        }
+    }
+
+    /**
+     * Atomically conditionally sets the tag value for this task.
+     * Among other applications, tags can be used as visit markers
+     * in tasks operating on graphs, as in methods that check: {@code
+     * if (task.compareAndSetForkJoinTaskTag((short)0, (short)1))}
+     * before processing, otherwise exiting because the node has
+     * already been visited.
+     *
+     * @param e the expected tag value
+     * @param tag the new tag value
+     * @return true if successful; i.e., the current value was
+     * equal to e and is now tag.
+     * @since 1.8
+     * @hide
+     */
+    public final boolean compareAndSetForkJoinTaskTag(short e, short tag) {
+        for (int s;;) {
+            if ((short)(s = status) != e)
+                return false;
+            if (U.compareAndSwapInt(this, STATUS, s,
+                                    (s & ~SMASK) | (tag & SMASK)))
+                return true;
+        }
     }
 
     /**
@@ -1223,21 +1339,33 @@
     static final class AdaptedRunnable<T> extends ForkJoinTask<T>
         implements RunnableFuture<T> {
         final Runnable runnable;
-        final T resultOnCompletion;
         T result;
         AdaptedRunnable(Runnable runnable, T result) {
             if (runnable == null) throw new NullPointerException();
             this.runnable = runnable;
-            this.resultOnCompletion = result;
+            this.result = result; // OK to set this even before completion
         }
-        public T getRawResult() { return result; }
-        public void setRawResult(T v) { result = v; }
-        public boolean exec() {
-            runnable.run();
-            result = resultOnCompletion;
-            return true;
+        public final T getRawResult() { return result; }
+        public final void setRawResult(T v) { result = v; }
+        public final boolean exec() { runnable.run(); return true; }
+        public final void run() { invoke(); }
+        private static final long serialVersionUID = 5232453952276885070L;
+    }
+
+    /**
+     * Adaptor for Runnables without results
+     */
+    static final class AdaptedRunnableAction extends ForkJoinTask<Void>
+        implements RunnableFuture<Void> {
+        final Runnable runnable;
+        AdaptedRunnableAction(Runnable runnable) {
+            if (runnable == null) throw new NullPointerException();
+            this.runnable = runnable;
         }
-        public void run() { invoke(); }
+        public final Void getRawResult() { return null; }
+        public final void setRawResult(Void v) { }
+        public final boolean exec() { runnable.run(); return true; }
+        public final void run() { invoke(); }
         private static final long serialVersionUID = 5232453952276885070L;
     }
 
@@ -1252,9 +1380,9 @@
             if (callable == null) throw new NullPointerException();
             this.callable = callable;
         }
-        public T getRawResult() { return result; }
-        public void setRawResult(T v) { result = v; }
-        public boolean exec() {
+        public final T getRawResult() { return result; }
+        public final void setRawResult(T v) { result = v; }
+        public final boolean exec() {
             try {
                 result = callable.call();
                 return true;
@@ -1266,7 +1394,7 @@
                 throw new RuntimeException(ex);
             }
         }
-        public void run() { invoke(); }
+        public final void run() { invoke(); }
         private static final long serialVersionUID = 2838392045355241008L;
     }
 
@@ -1279,7 +1407,7 @@
      * @return the task
      */
     public static ForkJoinTask<?> adapt(Runnable runnable) {
-        return new AdaptedRunnable<Void>(runnable, null);
+        return new AdaptedRunnableAction(runnable);
     }
 
     /**
@@ -1313,11 +1441,10 @@
     private static final long serialVersionUID = -7721805057305804111L;
 
     /**
-     * Saves the state to a stream (that is, serializes it).
+     * Saves this task to a stream (that is, serializes it).
      *
      * @serialData the current run status and the exception thrown
      * during execution, or {@code null} if none
-     * @param s the stream
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
@@ -1326,9 +1453,7 @@
     }
 
     /**
-     * Reconstitutes the instance from a stream (that is, deserializes it).
-     *
-     * @param s the stream
+     * Reconstitutes this task from a stream (that is, deserializes it).
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
@@ -1339,16 +1464,18 @@
     }
 
     // Unsafe mechanics
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long statusOffset;
+    private static final sun.misc.Unsafe U;
+    private static final long STATUS;
+
     static {
         exceptionTableLock = new ReentrantLock();
         exceptionTableRefQueue = new ReferenceQueue<Object>();
         exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY];
         try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            statusOffset = UNSAFE.objectFieldOffset
-                (ForkJoinTask.class.getDeclaredField("status"));
+            U = sun.misc.Unsafe.getUnsafe();
+            Class<?> k = ForkJoinTask.class;
+            STATUS = U.objectFieldOffset
+                (k.getDeclaredField("status"));
         } catch (Exception e) {
             throw new Error(e);
         }
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java b/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
index d99ffe9..f31763c 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
@@ -6,10 +6,6 @@
 
 package java.util.concurrent;
 
-import java.util.Collection;
-import java.util.concurrent.RejectedExecutionException;
-import libcore.util.SneakyThrow;
-
 /**
  * A thread managed by a {@link ForkJoinPool}, which executes
  * {@link ForkJoinTask}s.
@@ -27,238 +23,20 @@
  */
 public class ForkJoinWorkerThread extends Thread {
     /*
-     * Overview:
-     *
      * ForkJoinWorkerThreads are managed by ForkJoinPools and perform
-     * ForkJoinTasks. This class includes bookkeeping in support of
-     * worker activation, suspension, and lifecycle control described
-     * in more detail in the internal documentation of class
-     * ForkJoinPool. And as described further below, this class also
-     * includes special-cased support for some ForkJoinTask
-     * methods. But the main mechanics involve work-stealing:
+     * ForkJoinTasks. For explanation, see the internal documentation
+     * of class ForkJoinPool.
      *
-     * Work-stealing queues are special forms of Deques that support
-     * only three of the four possible end-operations -- push, pop,
-     * and deq (aka steal), under the further constraints that push
-     * and pop are called only from the owning thread, while deq may
-     * be called from other threads.  (If you are unfamiliar with
-     * them, you probably want to read Herlihy and Shavit's book "The
-     * Art of Multiprocessor programming", chapter 16 describing these
-     * in more detail before proceeding.)  The main work-stealing
-     * queue design is roughly similar to those in the papers "Dynamic
-     * Circular Work-Stealing Deque" by Chase and Lev, SPAA 2005
-     * (http://research.sun.com/scalable/pubs/index.html) and
-     * "Idempotent work stealing" by Michael, Saraswat, and Vechev,
-     * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
-     * The main differences ultimately stem from gc requirements that
-     * we null out taken slots as soon as we can, to maintain as small
-     * a footprint as possible even in programs generating huge
-     * numbers of tasks. To accomplish this, we shift the CAS
-     * arbitrating pop vs deq (steal) from being on the indices
-     * ("queueBase" and "queueTop") to the slots themselves (mainly
-     * via method "casSlotNull()"). So, both a successful pop and deq
-     * mainly entail a CAS of a slot from non-null to null.  Because
-     * we rely on CASes of references, we do not need tag bits on
-     * queueBase or queueTop.  They are simple ints as used in any
-     * circular array-based queue (see for example ArrayDeque).
-     * Updates to the indices must still be ordered in a way that
-     * guarantees that queueTop == queueBase means the queue is empty,
-     * but otherwise may err on the side of possibly making the queue
-     * appear nonempty when a push, pop, or deq have not fully
-     * committed. Note that this means that the deq operation,
-     * considered individually, is not wait-free. One thief cannot
-     * successfully continue until another in-progress one (or, if
-     * previously empty, a push) completes.  However, in the
-     * aggregate, we ensure at least probabilistic non-blockingness.
-     * If an attempted steal fails, a thief always chooses a different
-     * random victim target to try next. So, in order for one thief to
-     * progress, it suffices for any in-progress deq or new push on
-     * any empty queue to complete.
-     *
-     * This approach also enables support for "async mode" where local
-     * task processing is in FIFO, not LIFO order; simply by using a
-     * version of deq rather than pop when locallyFifo is true (as set
-     * by the ForkJoinPool).  This allows use in message-passing
-     * frameworks in which tasks are never joined.  However neither
-     * mode considers affinities, loads, cache localities, etc, so
-     * rarely provide the best possible performance on a given
-     * machine, but portably provide good throughput by averaging over
-     * these factors.  (Further, even if we did try to use such
-     * information, we do not usually have a basis for exploiting
-     * it. For example, some sets of tasks profit from cache
-     * affinities, but others are harmed by cache pollution effects.)
-     *
-     * When a worker would otherwise be blocked waiting to join a
-     * task, it first tries a form of linear helping: Each worker
-     * records (in field currentSteal) the most recent task it stole
-     * from some other worker. Plus, it records (in field currentJoin)
-     * the task it is currently actively joining. Method joinTask uses
-     * these markers to try to find a worker to help (i.e., steal back
-     * a task from and execute it) that could hasten completion of the
-     * actively joined task. In essence, the joiner executes a task
-     * that would be on its own local deque had the to-be-joined task
-     * not been stolen. This may be seen as a conservative variant of
-     * the approach in Wagner & Calder "Leapfrogging: a portable
-     * technique for implementing efficient futures" SIGPLAN Notices,
-     * 1993 (http://portal.acm.org/citation.cfm?id=155354). It differs
-     * in that: (1) We only maintain dependency links across workers
-     * upon steals, rather than use per-task bookkeeping.  This may
-     * require a linear scan of workers array to locate stealers, but
-     * usually doesn't because stealers leave hints (that may become
-     * stale/wrong) of where to locate them. This isolates cost to
-     * when it is needed, rather than adding to per-task overhead.
-     * (2) It is "shallow", ignoring nesting and potentially cyclic
-     * mutual steals.  (3) It is intentionally racy: field currentJoin
-     * is updated only while actively joining, which means that we
-     * miss links in the chain during long-lived tasks, GC stalls etc
-     * (which is OK since blocking in such cases is usually a good
-     * idea).  (4) We bound the number of attempts to find work (see
-     * MAX_HELP) and fall back to suspending the worker and if
-     * necessary replacing it with another.
-     *
-     * Efficient implementation of these algorithms currently relies
-     * on an uncomfortable amount of "Unsafe" mechanics. To maintain
-     * correct orderings, reads and writes of variable queueBase
-     * require volatile ordering.  Variable queueTop need not be
-     * volatile because non-local reads always follow those of
-     * queueBase.  Similarly, because they are protected by volatile
-     * queueBase reads, reads of the queue array and its slots by
-     * other threads do not need volatile load semantics, but writes
-     * (in push) require store order and CASes (in pop and deq)
-     * require (volatile) CAS semantics.  (Michael, Saraswat, and
-     * Vechev's algorithm has similar properties, but without support
-     * for nulling slots.)  Since these combinations aren't supported
-     * using ordinary volatiles, the only way to accomplish these
-     * efficiently is to use direct Unsafe calls. (Using external
-     * AtomicIntegers and AtomicReferenceArrays for the indices and
-     * array is significantly slower because of memory locality and
-     * indirection effects.)
-     *
-     * Further, performance on most platforms is very sensitive to
-     * placement and sizing of the (resizable) queue array.  Even
-     * though these queues don't usually become all that big, the
-     * initial size must be large enough to counteract cache
-     * contention effects across multiple queues (especially in the
-     * presence of GC cardmarking). Also, to improve thread-locality,
-     * queues are initialized after starting.
+     * This class just maintains links to its pool and WorkQueue.  The
+     * pool field is set immediately upon construction, but the
+     * workQueue field is not set until a call to registerWorker
+     * completes. This leads to a visibility race, that is tolerated
+     * by requiring that the workQueue field is only accessed by the
+     * owning thread.
      */
 
-    /**
-     * Mask for pool indices encoded as shorts
-     */
-    private static final int  SMASK  = 0xffff;
-
-    /**
-     * Capacity of work-stealing queue array upon initialization.
-     * Must be a power of two. Initial size must be at least 4, but is
-     * padded to minimize cache effects.
-     */
-    private static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
-
-    /**
-     * Maximum size for queue array. Must be a power of two
-     * less than or equal to 1 << (31 - width of array entry) to
-     * ensure lack of index wraparound, but is capped at a lower
-     * value to help users trap runaway computations.
-     */
-    private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 24; // 16M
-
-    /**
-     * The work-stealing queue array. Size must be a power of two.
-     * Initialized when started (as opposed to when constructed), to
-     * improve memory locality.
-     */
-    ForkJoinTask<?>[] queue;
-
-    /**
-     * The pool this thread works in. Accessed directly by ForkJoinTask.
-     */
-    final ForkJoinPool pool;
-
-    /**
-     * Index (mod queue.length) of next queue slot to push to or pop
-     * from. It is written only by owner thread, and accessed by other
-     * threads only after reading (volatile) queueBase.  Both queueTop
-     * and queueBase are allowed to wrap around on overflow, but
-     * (queueTop - queueBase) still estimates size.
-     */
-    int queueTop;
-
-    /**
-     * Index (mod queue.length) of least valid queue slot, which is
-     * always the next position to steal from if nonempty.
-     */
-    volatile int queueBase;
-
-    /**
-     * The index of most recent stealer, used as a hint to avoid
-     * traversal in method helpJoinTask. This is only a hint because a
-     * worker might have had multiple steals and this only holds one
-     * of them (usually the most current). Declared non-volatile,
-     * relying on other prevailing sync to keep reasonably current.
-     */
-    int stealHint;
-
-    /**
-     * Index of this worker in pool array. Set once by pool before
-     * running, and accessed directly by pool to locate this worker in
-     * its workers array.
-     */
-    final int poolIndex;
-
-    /**
-     * Encoded record for pool task waits. Usages are always
-     * surrounded by volatile reads/writes
-     */
-    int nextWait;
-
-    /**
-     * Complement of poolIndex, offset by count of entries of task
-     * waits. Accessed by ForkJoinPool to manage event waiters.
-     */
-    volatile int eventCount;
-
-    /**
-     * Seed for random number generator for choosing steal victims.
-     * Uses Marsaglia xorshift. Must be initialized as nonzero.
-     */
-    int seed;
-
-    /**
-     * Number of steals. Directly accessed (and reset) by pool when
-     * idle.
-     */
-    int stealCount;
-
-    /**
-     * True if this worker should or did terminate
-     */
-    volatile boolean terminate;
-
-    /**
-     * Set to true before LockSupport.park; false on return
-     */
-    volatile boolean parked;
-
-    /**
-     * True if use local fifo, not default lifo, for local polling.
-     * Shadows value from ForkJoinPool.
-     */
-    final boolean locallyFifo;
-
-    /**
-     * The task most recently stolen from another worker (or
-     * submission queue).  All uses are surrounded by enough volatile
-     * reads/writes to maintain as non-volatile.
-     */
-    ForkJoinTask<?> currentSteal;
-
-    /**
-     * The task currently being joined, set only when actively trying
-     * to help other stealers in helpJoinTask. All uses are surrounded
-     * by enough volatile reads/writes to maintain as non-volatile.
-     */
-    ForkJoinTask<?> currentJoin;
+    final ForkJoinPool pool;                // the pool this thread works in
+    final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
 
     /**
      * Creates a ForkJoinWorkerThread operating in the given pool.
@@ -267,20 +45,12 @@
      * @throws NullPointerException if pool is null
      */
     protected ForkJoinWorkerThread(ForkJoinPool pool) {
-        super(pool.nextWorkerName());
+        // Use a placeholder until a useful name can be set in registerWorker
+        super("aForkJoinWorkerThread");
         this.pool = pool;
-        int k = pool.registerWorker(this);
-        poolIndex = k;
-        eventCount = ~k & SMASK; // clear wait count
-        locallyFifo = pool.locallyFifo;
-        Thread.UncaughtExceptionHandler ueh = pool.ueh;
-        if (ueh != null)
-            setUncaughtExceptionHandler(ueh);
-        setDaemon(true);
+        this.workQueue = pool.registerWorker(this);
     }
 
-    // Public methods
-
     /**
      * Returns the pool hosting this thread.
      *
@@ -300,28 +70,9 @@
      * @return the index number
      */
     public int getPoolIndex() {
-        return poolIndex;
+        return workQueue.poolIndex;
     }
 
-    // Randomization
-
-    /**
-     * Computes next value for random victim probes and backoffs.
-     * Scans don't require a very high quality generator, but also not
-     * a crummy one.  Marsaglia xor-shift is cheap and works well
-     * enough.  Note: This is manually inlined in FJP.scan() to avoid
-     * writes inside busy loops.
-     */
-    private int nextSeed() {
-        int r = seed;
-        r ^= r << 13;
-        r ^= r >>> 17;
-        r ^= r << 5;
-        return seed = r;
-    }
-
-    // Run State management
-
     /**
      * Initializes internal state after construction but before
      * processing any tasks. If you override this method, you must
@@ -332,9 +83,6 @@
      * processing tasks.
      */
     protected void onStart() {
-        queue = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY];
-        int r = ForkJoinPool.workerSeedGenerator.nextInt();
-        seed = (r == 0) ? 1 : r; //  must be nonzero
     }
 
     /**
@@ -346,17 +94,6 @@
      * to an unrecoverable error, or {@code null} if completed normally
      */
     protected void onTermination(Throwable exception) {
-        try {
-            terminate = true;
-            cancelTasks();
-            pool.deregisterWorker(this, exception);
-        } catch (Throwable ex) {        // Shouldn't ever happen
-            if (exception == null)      // but if so, at least rethrown
-                exception = ex;
-        } finally {
-            if (exception != null)
-                SneakyThrow.sneakyThrow(exception); // android-changed
-        }
     }
 
     /**
@@ -368,603 +105,18 @@
         Throwable exception = null;
         try {
             onStart();
-            pool.work(this);
+            pool.runWorker(workQueue);
         } catch (Throwable ex) {
             exception = ex;
         } finally {
-            onTermination(exception);
-        }
-    }
-
-    /*
-     * Intrinsics-based atomic writes for queue slots. These are
-     * basically the same as methods in AtomicReferenceArray, but
-     * specialized for (1) ForkJoinTask elements (2) requirement that
-     * nullness and bounds checks have already been performed by
-     * callers and (3) effective offsets are known not to overflow
-     * from int to long (because of MAXIMUM_QUEUE_CAPACITY). We don't
-     * need corresponding version for reads: plain array reads are OK
-     * because they are protected by other volatile reads and are
-     * confirmed by CASes.
-     *
-     * Most uses don't actually call these methods, but instead
-     * contain inlined forms that enable more predictable
-     * optimization.  We don't define the version of write used in
-     * pushTask at all, but instead inline there a store-fenced array
-     * slot write.
-     *
-     * Also in most methods, as a performance (not correctness) issue,
-     * we'd like to encourage compilers not to arbitrarily postpone
-     * setting queueTop after writing slot.  Currently there is no
-     * intrinsic for arranging this, but using Unsafe putOrderedInt
-     * may be a preferable strategy on some compilers even though its
-     * main effect is a pre-, not post- fence. To simplify possible
-     * changes, the option is left in comments next to the associated
-     * assignments.
-     */
-
-    /**
-     * CASes slot i of array q from t to null. Caller must ensure q is
-     * non-null and index is in range.
-     */
-    private static final boolean casSlotNull(ForkJoinTask<?>[] q, int i,
-                                             ForkJoinTask<?> t) {
-        return UNSAFE.compareAndSwapObject(q, (i << ASHIFT) + ABASE, t, null);
-    }
-
-    /**
-     * Performs a volatile write of the given task at given slot of
-     * array q.  Caller must ensure q is non-null and index is in
-     * range. This method is used only during resets and backouts.
-     */
-    private static final void writeSlot(ForkJoinTask<?>[] q, int i,
-                                        ForkJoinTask<?> t) {
-        UNSAFE.putObjectVolatile(q, (i << ASHIFT) + ABASE, t);
-    }
-
-    // queue methods
-
-    /**
-     * Pushes a task. Call only from this thread.
-     *
-     * @param t the task. Caller must ensure non-null.
-     */
-    final void pushTask(ForkJoinTask<?> t) {
-        ForkJoinTask<?>[] q; int s, m;
-        if ((q = queue) != null) {    // ignore if queue removed
-            long u = (((s = queueTop) & (m = q.length - 1)) << ASHIFT) + ABASE;
-            UNSAFE.putOrderedObject(q, u, t);
-            queueTop = s + 1;         // or use putOrderedInt
-            if ((s -= queueBase) <= 2)
-                pool.signalWork();
-            else if (s == m)
-                growQueue();
-        }
-    }
-
-    /**
-     * Creates or doubles queue array.  Transfers elements by
-     * emulating steals (deqs) from old array and placing, oldest
-     * first, into new array.
-     */
-    private void growQueue() {
-        ForkJoinTask<?>[] oldQ = queue;
-        int size = oldQ != null ? oldQ.length << 1 : INITIAL_QUEUE_CAPACITY;
-        if (size > MAXIMUM_QUEUE_CAPACITY)
-            throw new RejectedExecutionException("Queue capacity exceeded");
-        if (size < INITIAL_QUEUE_CAPACITY)
-            size = INITIAL_QUEUE_CAPACITY;
-        ForkJoinTask<?>[] q = queue = new ForkJoinTask<?>[size];
-        int mask = size - 1;
-        int top = queueTop;
-        int oldMask;
-        if (oldQ != null && (oldMask = oldQ.length - 1) >= 0) {
-            for (int b = queueBase; b != top; ++b) {
-                long u = ((b & oldMask) << ASHIFT) + ABASE;
-                Object x = UNSAFE.getObjectVolatile(oldQ, u);
-                if (x != null && UNSAFE.compareAndSwapObject(oldQ, u, x, null))
-                    UNSAFE.putObjectVolatile
-                        (q, ((b & mask) << ASHIFT) + ABASE, x);
+            try {
+                onTermination(exception);
+            } catch (Throwable ex) {
+                if (exception == null)
+                    exception = ex;
+            } finally {
+                pool.deregisterWorker(this, exception);
             }
         }
     }
-
-    /**
-     * Tries to take a task from the base of the queue, failing if
-     * empty or contended. Note: Specializations of this code appear
-     * in locallyDeqTask and elsewhere.
-     *
-     * @return a task, or null if none or contended
-     */
-    final ForkJoinTask<?> deqTask() {
-        ForkJoinTask<?> t; ForkJoinTask<?>[] q; int b, i;
-        if (queueTop != (b = queueBase) &&
-            (q = queue) != null && // must read q after b
-            (i = (q.length - 1) & b) >= 0 &&
-            (t = q[i]) != null && queueBase == b &&
-            UNSAFE.compareAndSwapObject(q, (i << ASHIFT) + ABASE, t, null)) {
-            queueBase = b + 1;
-            return t;
-        }
-        return null;
-    }
-
-    /**
-     * Tries to take a task from the base of own queue.  Called only
-     * by this thread.
-     *
-     * @return a task, or null if none
-     */
-    final ForkJoinTask<?> locallyDeqTask() {
-        ForkJoinTask<?> t; int m, b, i;
-        ForkJoinTask<?>[] q = queue;
-        if (q != null && (m = q.length - 1) >= 0) {
-            while (queueTop != (b = queueBase)) {
-                if ((t = q[i = m & b]) != null &&
-                    queueBase == b &&
-                    UNSAFE.compareAndSwapObject(q, (i << ASHIFT) + ABASE,
-                                                t, null)) {
-                    queueBase = b + 1;
-                    return t;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns a popped task, or null if empty.
-     * Called only by this thread.
-     */
-    private ForkJoinTask<?> popTask() {
-        int m;
-        ForkJoinTask<?>[] q = queue;
-        if (q != null && (m = q.length - 1) >= 0) {
-            for (int s; (s = queueTop) != queueBase;) {
-                int i = m & --s;
-                long u = (i << ASHIFT) + ABASE; // raw offset
-                ForkJoinTask<?> t = q[i];
-                if (t == null)   // lost to stealer
-                    break;
-                if (UNSAFE.compareAndSwapObject(q, u, t, null)) {
-                    queueTop = s; // or putOrderedInt
-                    return t;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Specialized version of popTask to pop only if topmost element
-     * is the given task. Called only by this thread.
-     *
-     * @param t the task. Caller must ensure non-null.
-     */
-    final boolean unpushTask(ForkJoinTask<?> t) {
-        ForkJoinTask<?>[] q;
-        int s;
-        if ((q = queue) != null && (s = queueTop) != queueBase &&
-            UNSAFE.compareAndSwapObject
-            (q, (((q.length - 1) & --s) << ASHIFT) + ABASE, t, null)) {
-            queueTop = s; // or putOrderedInt
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Returns next task, or null if empty or contended.
-     */
-    final ForkJoinTask<?> peekTask() {
-        int m;
-        ForkJoinTask<?>[] q = queue;
-        if (q == null || (m = q.length - 1) < 0)
-            return null;
-        int i = locallyFifo ? queueBase : (queueTop - 1);
-        return q[i & m];
-    }
-
-    // Support methods for ForkJoinPool
-
-    /**
-     * Runs the given task, plus any local tasks until queue is empty
-     */
-    final void execTask(ForkJoinTask<?> t) {
-        currentSteal = t;
-        for (;;) {
-            if (t != null)
-                t.doExec();
-            if (queueTop == queueBase)
-                break;
-            t = locallyFifo ? locallyDeqTask() : popTask();
-        }
-        ++stealCount;
-        currentSteal = null;
-    }
-
-    /**
-     * Removes and cancels all tasks in queue.  Can be called from any
-     * thread.
-     */
-    final void cancelTasks() {
-        ForkJoinTask<?> cj = currentJoin; // try to cancel ongoing tasks
-        if (cj != null && cj.status >= 0)
-            cj.cancelIgnoringExceptions();
-        ForkJoinTask<?> cs = currentSteal;
-        if (cs != null && cs.status >= 0)
-            cs.cancelIgnoringExceptions();
-        while (queueBase != queueTop) {
-            ForkJoinTask<?> t = deqTask();
-            if (t != null)
-                t.cancelIgnoringExceptions();
-        }
-    }
-
-    /**
-     * Drains tasks to given collection c.
-     *
-     * @return the number of tasks drained
-     */
-    final int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
-        int n = 0;
-        while (queueBase != queueTop) {
-            ForkJoinTask<?> t = deqTask();
-            if (t != null) {
-                c.add(t);
-                ++n;
-            }
-        }
-        return n;
-    }
-
-    // Support methods for ForkJoinTask
-
-    /**
-     * Returns an estimate of the number of tasks in the queue.
-     */
-    final int getQueueSize() {
-        return queueTop - queueBase;
-    }
-
-    /**
-     * Gets and removes a local task.
-     *
-     * @return a task, if available
-     */
-    final ForkJoinTask<?> pollLocalTask() {
-        return locallyFifo ? locallyDeqTask() : popTask();
-    }
-
-    /**
-     * Gets and removes a local or stolen task.
-     *
-     * @return a task, if available
-     */
-    final ForkJoinTask<?> pollTask() {
-        ForkJoinWorkerThread[] ws;
-        ForkJoinTask<?> t = pollLocalTask();
-        if (t != null || (ws = pool.workers) == null)
-            return t;
-        int n = ws.length; // cheap version of FJP.scan
-        int steps = n << 1;
-        int r = nextSeed();
-        int i = 0;
-        while (i < steps) {
-            ForkJoinWorkerThread w = ws[(i++ + r) & (n - 1)];
-            if (w != null && w.queueBase != w.queueTop && w.queue != null) {
-                if ((t = w.deqTask()) != null)
-                    return t;
-                i = 0;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * The maximum stolen->joining link depth allowed in helpJoinTask,
-     * as well as the maximum number of retries (allowing on average
-     * one staleness retry per level) per attempt to instead try
-     * compensation.  Depths for legitimate chains are unbounded, but
-     * we use a fixed constant to avoid (otherwise unchecked) cycles
-     * and bound staleness of traversal parameters at the expense of
-     * sometimes blocking when we could be helping.
-     */
-    private static final int MAX_HELP = 16;
-
-    /**
-     * Possibly runs some tasks and/or blocks, until joinMe is done.
-     *
-     * @param joinMe the task to join
-     * @return completion status on exit
-     */
-    final int joinTask(ForkJoinTask<?> joinMe) {
-        ForkJoinTask<?> prevJoin = currentJoin;
-        currentJoin = joinMe;
-        for (int s, retries = MAX_HELP;;) {
-            if ((s = joinMe.status) < 0) {
-                currentJoin = prevJoin;
-                return s;
-            }
-            if (retries > 0) {
-                if (queueTop != queueBase) {
-                    if (!localHelpJoinTask(joinMe))
-                        retries = 0;           // cannot help
-                }
-                else if (retries == MAX_HELP >>> 1) {
-                    --retries;                 // check uncommon case
-                    if (tryDeqAndExec(joinMe) >= 0)
-                        Thread.yield();        // for politeness
-                }
-                else
-                    retries = helpJoinTask(joinMe) ? MAX_HELP : retries - 1;
-            }
-            else {
-                retries = MAX_HELP;           // restart if not done
-                pool.tryAwaitJoin(joinMe);
-            }
-        }
-    }
-
-    /**
-     * If present, pops and executes the given task, or any other
-     * cancelled task
-     *
-     * @return false if any other non-cancelled task exists in local queue
-     */
-    private boolean localHelpJoinTask(ForkJoinTask<?> joinMe) {
-        int s, i; ForkJoinTask<?>[] q; ForkJoinTask<?> t;
-        if ((s = queueTop) != queueBase && (q = queue) != null &&
-            (i = (q.length - 1) & --s) >= 0 &&
-            (t = q[i]) != null) {
-            if (t != joinMe && t.status >= 0)
-                return false;
-            if (UNSAFE.compareAndSwapObject
-                (q, (i << ASHIFT) + ABASE, t, null)) {
-                queueTop = s;           // or putOrderedInt
-                t.doExec();
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Tries to locate and execute tasks for a stealer of the given
-     * task, or in turn one of its stealers, Traces
-     * currentSteal->currentJoin links looking for a thread working on
-     * a descendant of the given task and with a non-empty queue to
-     * steal back and execute tasks from.  The implementation is very
-     * branchy to cope with potential inconsistencies or loops
-     * encountering chains that are stale, unknown, or of length
-     * greater than MAX_HELP links.  All of these cases are dealt with
-     * by just retrying by caller.
-     *
-     * @param joinMe the task to join
-     * @return true if ran a task
-     */
-    private boolean helpJoinTask(ForkJoinTask<?> joinMe) {
-        boolean helped = false;
-        int m = pool.scanGuard & SMASK;
-        ForkJoinWorkerThread[] ws = pool.workers;
-        if (ws != null && ws.length > m && joinMe.status >= 0) {
-            int levels = MAX_HELP;              // remaining chain length
-            ForkJoinTask<?> task = joinMe;      // base of chain
-            outer:for (ForkJoinWorkerThread thread = this;;) {
-                // Try to find v, the stealer of task, by first using hint
-                ForkJoinWorkerThread v = ws[thread.stealHint & m];
-                if (v == null || v.currentSteal != task) {
-                    for (int j = 0; ;) {        // search array
-                        if ((v = ws[j]) != null && v.currentSteal == task) {
-                            thread.stealHint = j;
-                            break;              // save hint for next time
-                        }
-                        if (++j > m)
-                            break outer;        // can't find stealer
-                    }
-                }
-                // Try to help v, using specialized form of deqTask
-                for (;;) {
-                    ForkJoinTask<?>[] q; int b, i;
-                    if (joinMe.status < 0)
-                        break outer;
-                    if ((b = v.queueBase) == v.queueTop ||
-                        (q = v.queue) == null ||
-                        (i = (q.length-1) & b) < 0)
-                        break;                  // empty
-                    long u = (i << ASHIFT) + ABASE;
-                    ForkJoinTask<?> t = q[i];
-                    if (task.status < 0)
-                        break outer;            // stale
-                    if (t != null && v.queueBase == b &&
-                        UNSAFE.compareAndSwapObject(q, u, t, null)) {
-                        v.queueBase = b + 1;
-                        v.stealHint = poolIndex;
-                        ForkJoinTask<?> ps = currentSteal;
-                        currentSteal = t;
-                        t.doExec();
-                        currentSteal = ps;
-                        helped = true;
-                    }
-                }
-                // Try to descend to find v's stealer
-                ForkJoinTask<?> next = v.currentJoin;
-                if (--levels > 0 && task.status >= 0 &&
-                    next != null && next != task) {
-                    task = next;
-                    thread = v;
-                }
-                else
-                    break;  // max levels, stale, dead-end, or cyclic
-            }
-        }
-        return helped;
-    }
-
-    /**
-     * Performs an uncommon case for joinTask: If task t is at base of
-     * some workers queue, steals and executes it.
-     *
-     * @param t the task
-     * @return t's status
-     */
-    private int tryDeqAndExec(ForkJoinTask<?> t) {
-        int m = pool.scanGuard & SMASK;
-        ForkJoinWorkerThread[] ws = pool.workers;
-        if (ws != null && ws.length > m && t.status >= 0) {
-            for (int j = 0; j <= m; ++j) {
-                ForkJoinTask<?>[] q; int b, i;
-                ForkJoinWorkerThread v = ws[j];
-                if (v != null &&
-                    (b = v.queueBase) != v.queueTop &&
-                    (q = v.queue) != null &&
-                    (i = (q.length - 1) & b) >= 0 &&
-                    q[i] ==  t) {
-                    long u = (i << ASHIFT) + ABASE;
-                    if (v.queueBase == b &&
-                        UNSAFE.compareAndSwapObject(q, u, t, null)) {
-                        v.queueBase = b + 1;
-                        v.stealHint = poolIndex;
-                        ForkJoinTask<?> ps = currentSteal;
-                        currentSteal = t;
-                        t.doExec();
-                        currentSteal = ps;
-                    }
-                    break;
-                }
-            }
-        }
-        return t.status;
-    }
-
-    /**
-     * Implements ForkJoinTask.getSurplusQueuedTaskCount().  Returns
-     * an estimate of the number of tasks, offset by a function of
-     * number of idle workers.
-     *
-     * This method provides a cheap heuristic guide for task
-     * partitioning when programmers, frameworks, tools, or languages
-     * have little or no idea about task granularity.  In essence by
-     * offering this method, we ask users only about tradeoffs in
-     * overhead vs expected throughput and its variance, rather than
-     * how finely to partition tasks.
-     *
-     * In a steady state strict (tree-structured) computation, each
-     * thread makes available for stealing enough tasks for other
-     * threads to remain active. Inductively, if all threads play by
-     * the same rules, each thread should make available only a
-     * constant number of tasks.
-     *
-     * The minimum useful constant is just 1. But using a value of 1
-     * would require immediate replenishment upon each steal to
-     * maintain enough tasks, which is infeasible.  Further,
-     * partitionings/granularities of offered tasks should minimize
-     * steal rates, which in general means that threads nearer the top
-     * of computation tree should generate more than those nearer the
-     * bottom. In perfect steady state, each thread is at
-     * approximately the same level of computation tree. However,
-     * producing extra tasks amortizes the uncertainty of progress and
-     * diffusion assumptions.
-     *
-     * So, users will want to use values larger, but not much larger
-     * than 1 to both smooth over transient shortages and hedge
-     * against uneven progress; as traded off against the cost of
-     * extra task overhead. We leave the user to pick a threshold
-     * value to compare with the results of this call to guide
-     * decisions, but recommend values such as 3.
-     *
-     * When all threads are active, it is on average OK to estimate
-     * surplus strictly locally. In steady-state, if one thread is
-     * maintaining say 2 surplus tasks, then so are others. So we can
-     * just use estimated queue length (although note that (queueTop -
-     * queueBase) can be an overestimate because of stealers lagging
-     * increments of queueBase).  However, this strategy alone leads
-     * to serious mis-estimates in some non-steady-state conditions
-     * (ramp-up, ramp-down, other stalls). We can detect many of these
-     * by further considering the number of "idle" threads, that are
-     * known to have zero queued tasks, so compensate by a factor of
-     * (#idle/#active) threads.
-     */
-    final int getEstimatedSurplusTaskCount() {
-        return queueTop - queueBase - pool.idlePerActive();
-    }
-
-    /**
-     * Runs tasks until {@code pool.isQuiescent()}. We piggyback on
-     * pool's active count ctl maintenance, but rather than blocking
-     * when tasks cannot be found, we rescan until all others cannot
-     * find tasks either. The bracketing by pool quiescerCounts
-     * updates suppresses pool auto-shutdown mechanics that could
-     * otherwise prematurely terminate the pool because all threads
-     * appear to be inactive.
-     */
-    final void helpQuiescePool() {
-        boolean active = true;
-        ForkJoinTask<?> ps = currentSteal; // to restore below
-        ForkJoinPool p = pool;
-        p.addQuiescerCount(1);
-        for (;;) {
-            ForkJoinWorkerThread[] ws = p.workers;
-            ForkJoinWorkerThread v = null;
-            int n;
-            if (queueTop != queueBase)
-                v = this;
-            else if (ws != null && (n = ws.length) > 1) {
-                ForkJoinWorkerThread w;
-                int r = nextSeed(); // cheap version of FJP.scan
-                int steps = n << 1;
-                for (int i = 0; i < steps; ++i) {
-                    if ((w = ws[(i + r) & (n - 1)]) != null &&
-                        w.queueBase != w.queueTop) {
-                        v = w;
-                        break;
-                    }
-                }
-            }
-            if (v != null) {
-                ForkJoinTask<?> t;
-                if (!active) {
-                    active = true;
-                    p.addActiveCount(1);
-                }
-                if ((t = (v != this) ? v.deqTask() :
-                     locallyFifo ? locallyDeqTask() : popTask()) != null) {
-                    currentSteal = t;
-                    t.doExec();
-                    currentSteal = ps;
-                }
-            }
-            else {
-                if (active) {
-                    active = false;
-                    p.addActiveCount(-1);
-                }
-                if (p.isQuiescent()) {
-                    p.addActiveCount(1);
-                    p.addQuiescerCount(-1);
-                    break;
-                }
-            }
-        }
-    }
-
-    // Unsafe mechanics
-    private static final sun.misc.Unsafe UNSAFE;
-    private static final long ABASE;
-    private static final int ASHIFT;
-
-    static {
-        int s;
-        try {
-            UNSAFE = sun.misc.Unsafe.getUnsafe();
-            Class<?> a = ForkJoinTask[].class;
-            ABASE = UNSAFE.arrayBaseOffset(a);
-            s = UNSAFE.arrayIndexScale(a);
-        } catch (Exception e) {
-            throw new Error(e);
-        }
-        if ((s & (s-1)) != 0)
-            throw new Error("data type scale not a power of two");
-        ASHIFT = 31 - Integer.numberOfLeadingZeros(s);
-    }
-
 }
diff --git a/luni/src/main/java/java/util/concurrent/Future.java b/luni/src/main/java/java/util/concurrent/Future.java
index 6a37729..32e8145 100644
--- a/luni/src/main/java/java/util/concurrent/Future.java
+++ b/luni/src/main/java/java/util/concurrent/Future.java
@@ -7,19 +7,19 @@
 package java.util.concurrent;
 
 /**
- * A <tt>Future</tt> represents the result of an asynchronous
+ * A {@code Future} represents the result of an asynchronous
  * computation.  Methods are provided to check if the computation is
  * complete, to wait for its completion, and to retrieve the result of
  * the computation.  The result can only be retrieved using method
- * <tt>get</tt> when the computation has completed, blocking if
+ * {@code get} when the computation has completed, blocking if
  * necessary until it is ready.  Cancellation is performed by the
- * <tt>cancel</tt> method.  Additional methods are provided to
+ * {@code cancel} method.  Additional methods are provided to
  * determine if the task completed normally or was cancelled. Once a
  * computation has completed, the computation cannot be cancelled.
- * If you would like to use a <tt>Future</tt> for the sake
+ * If you would like to use a {@code Future} for the sake
  * of cancellability but not provide a usable result, you can
  * declare types of the form {@code Future<?>} and
- * return <tt>null</tt> as a result of the underlying task.
+ * return {@code null} as a result of the underlying task.
  *
  * <p>
  * <b>Sample Usage</b> (Note that the following classes are all
@@ -43,16 +43,16 @@
  *   }
  * }}</pre>
  *
- * The {@link FutureTask} class is an implementation of <tt>Future</tt> that
- * implements <tt>Runnable</tt>, and so may be executed by an <tt>Executor</tt>.
- * For example, the above construction with <tt>submit</tt> could be replaced by:
+ * The {@link FutureTask} class is an implementation of {@code Future} that
+ * implements {@code Runnable}, and so may be executed by an {@code Executor}.
+ * For example, the above construction with {@code submit} could be replaced by:
  *  <pre> {@code
- *     FutureTask<String> future =
- *       new FutureTask<String>(new Callable<String>() {
- *         public String call() {
- *           return searcher.search(target);
- *       }});
- *     executor.execute(future);}</pre>
+ * FutureTask<String> future =
+ *   new FutureTask<String>(new Callable<String>() {
+ *     public String call() {
+ *       return searcher.search(target);
+ *   }});
+ * executor.execute(future);}</pre>
  *
  * <p>Memory consistency effects: Actions taken by the asynchronous computation
  * <a href="package-summary.html#MemoryVisibility"> <i>happen-before</i></a>
@@ -62,7 +62,7 @@
  * @see Executor
  * @since 1.5
  * @author Doug Lea
- * @param <V> The result type returned by this Future's <tt>get</tt> method
+ * @param <V> The result type returned by this Future's {@code get} method
  */
 public interface Future<V> {
 
@@ -70,41 +70,41 @@
      * Attempts to cancel execution of this task.  This attempt will
      * fail if the task has already completed, has already been cancelled,
      * or could not be cancelled for some other reason. If successful,
-     * and this task has not started when <tt>cancel</tt> is called,
+     * and this task has not started when {@code cancel} is called,
      * this task should never run.  If the task has already started,
-     * then the <tt>mayInterruptIfRunning</tt> parameter determines
+     * then the {@code mayInterruptIfRunning} parameter determines
      * whether the thread executing this task should be interrupted in
      * an attempt to stop the task.
      *
      * <p>After this method returns, subsequent calls to {@link #isDone} will
-     * always return <tt>true</tt>.  Subsequent calls to {@link #isCancelled}
-     * will always return <tt>true</tt> if this method returned <tt>true</tt>.
+     * always return {@code true}.  Subsequent calls to {@link #isCancelled}
+     * will always return {@code true} if this method returned {@code true}.
      *
-     * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
+     * @param mayInterruptIfRunning {@code true} if the thread executing this
      * task should be interrupted; otherwise, in-progress tasks are allowed
      * to complete
-     * @return <tt>false</tt> if the task could not be cancelled,
+     * @return {@code false} if the task could not be cancelled,
      * typically because it has already completed normally;
-     * <tt>true</tt> otherwise
+     * {@code true} otherwise
      */
     boolean cancel(boolean mayInterruptIfRunning);
 
     /**
-     * Returns <tt>true</tt> if this task was cancelled before it completed
+     * Returns {@code true} if this task was cancelled before it completed
      * normally.
      *
-     * @return <tt>true</tt> if this task was cancelled before it completed
+     * @return {@code true} if this task was cancelled before it completed
      */
     boolean isCancelled();
 
     /**
-     * Returns <tt>true</tt> if this task completed.
+     * Returns {@code true} if this task completed.
      *
      * Completion may be due to normal termination, an exception, or
      * cancellation -- in all of these cases, this method will return
-     * <tt>true</tt>.
+     * {@code true}.
      *
-     * @return <tt>true</tt> if this task completed
+     * @return {@code true} if this task completed
      */
     boolean isDone();
 
diff --git a/luni/src/main/java/java/util/concurrent/FutureTask.java b/luni/src/main/java/java/util/concurrent/FutureTask.java
index d51881d..114fe49 100644
--- a/luni/src/main/java/java/util/concurrent/FutureTask.java
+++ b/luni/src/main/java/java/util/concurrent/FutureTask.java
@@ -83,12 +83,11 @@
      *
      * @param s completed state value
      */
+    @SuppressWarnings("unchecked")
     private V report(int s) throws ExecutionException {
         Object x = outcome;
-        if (s == NORMAL) {
-            @SuppressWarnings("unchecked") V v = (V)x;
-            return v;
-        }
+        if (s == NORMAL)
+            return (V)x;
         if (s >= CANCELLED)
             throw new CancellationException();
         throw new ExecutionException((Throwable)x);
@@ -134,19 +133,23 @@
     }
 
     public boolean cancel(boolean mayInterruptIfRunning) {
-        if (state != NEW)
+        if (!(state == NEW &&
+              UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
+                  mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
             return false;
-        if (mayInterruptIfRunning) {
-            if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING))
-                return false;
-            Thread t = runner;
-            if (t != null)
-                t.interrupt();
-            UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state
+        try {    // in case call to interrupt throws exception
+            if (mayInterruptIfRunning) {
+                try {
+                    Thread t = runner;
+                    if (t != null)
+                        t.interrupt();
+                } finally { // final state
+                    UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
+                }
+            }
+        } finally {
+            finishCompletion();
         }
-        else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED))
-            return false;
-        finishCompletion();
         return true;
     }
 
@@ -363,7 +366,7 @@
      */
     private int awaitDone(boolean timed, long nanos)
         throws InterruptedException {
-        long last = timed ? System.nanoTime() : 0L;
+        final long deadline = timed ? System.nanoTime() + nanos : 0L;
         WaitNode q = null;
         boolean queued = false;
         for (;;) {
@@ -378,18 +381,19 @@
                     q.thread = null;
                 return s;
             }
+            else if (s == COMPLETING) // cannot time out yet
+                Thread.yield();
             else if (q == null)
                 q = new WaitNode();
             else if (!queued)
                 queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                      q.next = waiters, q);
             else if (timed) {
-                long now = System.nanoTime();
-                if ((nanos -= (now - last)) <= 0L) {
+                nanos = deadline - System.nanoTime();
+                if (nanos <= 0L) {
                     removeWaiter(q);
                     return state;
                 }
-                last = now;
                 LockSupport.parkNanos(this, nanos);
             }
             else
diff --git a/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java b/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
index 6f32c47..64b0bf1 100644
--- a/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
+++ b/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
@@ -21,7 +21,7 @@
  * An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
  * linked nodes.
  *
- * <p> The optional capacity bound constructor argument serves as a
+ * <p>The optional capacity bound constructor argument serves as a
  * way to prevent excessive expansion. The capacity, if unspecified,
  * is equal to {@link Integer#MAX_VALUE}.  Linked nodes are
  * dynamically created upon each insertion unless this would bring the
@@ -44,7 +44,7 @@
  */
 public class LinkedBlockingDeque<E>
     extends AbstractQueue<E>
-    implements BlockingDeque<E>,  java.io.Serializable {
+    implements BlockingDeque<E>, java.io.Serializable {
 
     /*
      * Implemented as a simple doubly-linked list protected by a
@@ -1123,11 +1123,10 @@
     }
 
     /**
-     * Saves the state of this deque to a stream (that is, serializes it).
+     * Saves this deque to a stream (that is, serializes it).
      *
      * @serialData The capacity (int), followed by elements (each an
      * {@code Object}) in the proper order, followed by a null
-     * @param s the stream
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
@@ -1148,8 +1147,6 @@
 
     /**
      * Reconstitutes this deque from a stream (that is, deserializes it).
-     *
-     * @param s the stream
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
diff --git a/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java b/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
index e8c9edb..0719828 100644
--- a/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
@@ -31,7 +31,7 @@
  * Linked queues typically have higher throughput than array-based queues but
  * less predictable performance in most concurrent applications.
  *
- * <p> The optional capacity bound constructor argument serves as a
+ * <p>The optional capacity bound constructor argument serves as a
  * way to prevent excessive queue expansion. The capacity, if unspecified,
  * is equal to {@link Integer#MAX_VALUE}.  Linked nodes are
  * dynamically created upon each insertion unless this would bring the
@@ -44,7 +44,6 @@
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this collection
- *
  */
 public class LinkedBlockingQueue<E> extends AbstractQueue<E>
         implements BlockingQueue<E>, java.io.Serializable {
@@ -188,7 +187,7 @@
     }
 
     /**
-     * Lock to prevent both puts and takes.
+     * Locks to prevent both puts and takes.
      */
     void fullyLock() {
         putLock.lock();
@@ -196,7 +195,7 @@
     }
 
     /**
-     * Unlock to allow both puts and takes.
+     * Unlocks to allow both puts and takes.
      */
     void fullyUnlock() {
         takeLock.unlock();
@@ -262,7 +261,6 @@
         }
     }
 
-
     // this doc comment is overridden to remove the reference to collections
     // greater in size than Integer.MAX_VALUE
     /**
@@ -335,7 +333,7 @@
      * necessary up to the specified wait time for space to become available.
      *
      * @return {@code true} if successful, or {@code false} if
-     *         the specified waiting time elapses before space is available.
+     *         the specified waiting time elapses before space is available
      * @throws InterruptedException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
      */
@@ -401,7 +399,6 @@
         return c >= 0;
     }
 
-
     public E take() throws InterruptedException {
         E x;
         int c = -1;
@@ -756,6 +753,7 @@
          * item to hand out so that if hasNext() reports true, we will
          * still have it to return even if lost race with a take etc.
          */
+
         private Node<E> current;
         private Node<E> lastRet;
         private E currentElement;
@@ -830,12 +828,11 @@
     }
 
     /**
-     * Saves the state to a stream (that is, serializes it).
+     * Saves this queue to a stream (that is, serializes it).
      *
      * @serialData The capacity is emitted (int), followed by all of
      * its elements (each an {@code Object}) in the proper order,
      * followed by a null
-     * @param s the stream
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
@@ -858,8 +855,6 @@
 
     /**
      * Reconstitutes this queue from a stream (that is, deserializes it).
-     *
-     * @param s the stream
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
diff --git a/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java b/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
index 2a3446e..cff5dbf 100644
--- a/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
+++ b/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
@@ -667,7 +667,7 @@
      * @return matched item, or e if unmatched on interrupt or timeout
      */
     private E awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) {
-        long lastTime = timed ? System.nanoTime() : 0L;
+        final long deadline = timed ? System.nanoTime() + nanos : 0L;
         Thread w = Thread.currentThread();
         int spins = -1; // initialized after first item and cancel checks
         ThreadLocalRandom randomYields = null; // bound if needed
@@ -698,10 +698,9 @@
                 s.waiter = w;                 // request unpark then recheck
             }
             else if (timed) {
-                long now = System.nanoTime();
-                if ((nanos -= now - lastTime) > 0)
+                nanos = deadline - System.nanoTime();
+                if (nanos > 0L)
                     LockSupport.parkNanos(this, nanos);
-                lastTime = now;
             }
             else {
                 LockSupport.park(this);
@@ -980,7 +979,6 @@
         return false;
     }
 
-
     /**
      * Creates an initially empty {@code LinkedTransferQueue}.
      */
@@ -1267,11 +1265,10 @@
     }
 
     /**
-     * Saves the state to a stream (that is, serializes it).
+     * Saves this queue to a stream (that is, serializes it).
      *
      * @serialData All of the elements (each an {@code E}) in
      * the proper order, followed by a null
-     * @param s the stream
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
@@ -1283,16 +1280,14 @@
     }
 
     /**
-     * Reconstitutes the Queue instance from a stream (that is,
-     * deserializes it).
-     *
-     * @param s the stream
+     * Reconstitutes this queue from a stream (that is, deserializes it).
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         s.defaultReadObject();
         for (;;) {
-            @SuppressWarnings("unchecked") E item = (E) s.readObject();
+            @SuppressWarnings("unchecked")
+            E item = (E) s.readObject();
             if (item == null)
                 break;
             else
diff --git a/luni/src/main/java/java/util/concurrent/Phaser.java b/luni/src/main/java/java/util/concurrent/Phaser.java
index 25ff743..a9adbe5 100644
--- a/luni/src/main/java/java/util/concurrent/Phaser.java
+++ b/luni/src/main/java/java/util/concurrent/Phaser.java
@@ -17,7 +17,7 @@
  * {@link java.util.concurrent.CountDownLatch CountDownLatch}
  * but supporting more flexible usage.
  *
- * <p> <b>Registration.</b> Unlike the case for other barriers, the
+ * <p><b>Registration.</b> Unlike the case for other barriers, the
  * number of parties <em>registered</em> to synchronize on a phaser
  * may vary over time.  Tasks may be registered at any time (using
  * methods {@link #register}, {@link #bulkRegister}, or forms of
@@ -30,7 +30,7 @@
  * (However, you can introduce such bookkeeping by subclassing this
  * class.)
  *
- * <p> <b>Synchronization.</b> Like a {@code CyclicBarrier}, a {@code
+ * <p><b>Synchronization.</b> Like a {@code CyclicBarrier}, a {@code
  * Phaser} may be repeatedly awaited.  Method {@link
  * #arriveAndAwaitAdvance} has effect analogous to {@link
  * java.util.concurrent.CyclicBarrier#await CyclicBarrier.await}. Each
@@ -74,7 +74,7 @@
  *
  * </ul>
  *
- * <p> <b>Termination.</b> A phaser may enter a <em>termination</em>
+ * <p><b>Termination.</b> A phaser may enter a <em>termination</em>
  * state, that may be checked using method {@link #isTerminated}. Upon
  * termination, all synchronization methods immediately return without
  * waiting for advance, as indicated by a negative return value.
@@ -89,7 +89,7 @@
  * also available to abruptly release waiting threads and allow them
  * to terminate.
  *
- * <p> <b>Tiering.</b> Phasers may be <em>tiered</em> (i.e.,
+ * <p><b>Tiering.</b> Phasers may be <em>tiered</em> (i.e.,
  * constructed in tree structures) to reduce contention. Phasers with
  * large numbers of parties that would otherwise experience heavy
  * synchronization contention costs may instead be set up so that
@@ -1065,7 +1065,7 @@
         final boolean timed;
         boolean wasInterrupted;
         long nanos;
-        long lastTime;
+        final long deadline;
         volatile Thread thread; // nulled to cancel wait
         QNode next;
 
@@ -1076,7 +1076,7 @@
             this.interruptible = interruptible;
             this.nanos = nanos;
             this.timed = timed;
-            this.lastTime = timed ? System.nanoTime() : 0L;
+            this.deadline = timed ? System.nanoTime() + nanos : 0L;
             thread = Thread.currentThread();
         }
 
@@ -1095,9 +1095,7 @@
             }
             if (timed) {
                 if (nanos > 0L) {
-                    long now = System.nanoTime();
-                    nanos -= now - lastTime;
-                    lastTime = now;
+                    nanos = deadline - System.nanoTime();
                 }
                 if (nanos <= 0L) {
                     thread = null;
@@ -1112,7 +1110,7 @@
                 return true;
             else if (!timed)
                 LockSupport.park(this);
-            else if (nanos > 0)
+            else if (nanos > 0L)
                 LockSupport.parkNanos(this, nanos);
             return isReleasable();
         }
diff --git a/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java b/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
index 26c72eb..0f9e715 100644
--- a/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
@@ -6,7 +6,8 @@
 
 package java.util.concurrent;
 
-import java.util.concurrent.locks.*;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.*;
 
 // BEGIN android-note
@@ -65,6 +66,7 @@
  * @author Doug Lea
  * @param <E> the type of elements held in this collection
  */
+@SuppressWarnings("unchecked")
 public class PriorityBlockingQueue<E> extends AbstractQueue<E>
     implements BlockingQueue<E>, java.io.Serializable {
     private static final long serialVersionUID = 5595510919245408276L;
@@ -311,7 +313,6 @@
      * @param k the position to fill
      * @param x the item to insert
      * @param array the heap array
-     * @param n heap size
      */
     private static <T> void siftUpComparable(int k, T x, Object[] array) {
         Comparable<? super T> key = (Comparable<? super T>) x;
@@ -351,39 +352,43 @@
      */
     private static <T> void siftDownComparable(int k, T x, Object[] array,
                                                int n) {
-        Comparable<? super T> key = (Comparable<? super T>)x;
-        int half = n >>> 1;           // loop while a non-leaf
-        while (k < half) {
-            int child = (k << 1) + 1; // assume left child is least
-            Object c = array[child];
-            int right = child + 1;
-            if (right < n &&
-                ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
-                c = array[child = right];
-            if (key.compareTo((T) c) <= 0)
-                break;
-            array[k] = c;
-            k = child;
+        if (n > 0) {
+            Comparable<? super T> key = (Comparable<? super T>)x;
+            int half = n >>> 1;           // loop while a non-leaf
+            while (k < half) {
+                int child = (k << 1) + 1; // assume left child is least
+                Object c = array[child];
+                int right = child + 1;
+                if (right < n &&
+                    ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
+                    c = array[child = right];
+                if (key.compareTo((T) c) <= 0)
+                    break;
+                array[k] = c;
+                k = child;
+            }
+            array[k] = key;
         }
-        array[k] = key;
     }
 
     private static <T> void siftDownUsingComparator(int k, T x, Object[] array,
                                                     int n,
                                                     Comparator<? super T> cmp) {
-        int half = n >>> 1;
-        while (k < half) {
-            int child = (k << 1) + 1;
-            Object c = array[child];
-            int right = child + 1;
-            if (right < n && cmp.compare((T) c, (T) array[right]) > 0)
-                c = array[child = right];
-            if (cmp.compare(x, (T) c) <= 0)
-                break;
-            array[k] = c;
-            k = child;
+        if (n > 0) {
+            int half = n >>> 1;
+            while (k < half) {
+                int child = (k << 1) + 1;
+                Object c = array[child];
+                int right = child + 1;
+                if (right < n && cmp.compare((T) c, (T) array[right]) > 0)
+                    c = array[child = right];
+                if (cmp.compare(x, (T) c) <= 0)
+                    break;
+                array[k] = c;
+                k = child;
+            }
+            array[k] = x;
         }
-        array[k] = x;
     }
 
     /**
@@ -866,10 +871,11 @@
     }
 
     /**
-     * Saves the state to a stream (that is, serializes it).  For
-     * compatibility with previous version of this class,
-     * elements are first copied to a java.util.PriorityQueue,
-     * which is then serialized.
+     * Saves this queue to a stream (that is, serializes it).
+     *
+     * For compatibility with previous version of this class, elements
+     * are first copied to a java.util.PriorityQueue, which is then
+     * serialized.
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
@@ -886,10 +892,7 @@
     }
 
     /**
-     * Reconstitutes the {@code PriorityBlockingQueue} instance from a stream
-     * (that is, deserializes it).
-     *
-     * @param s the stream
+     * Reconstitutes this queue from a stream (that is, deserializes it).
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
diff --git a/luni/src/main/java/java/util/concurrent/RecursiveAction.java b/luni/src/main/java/java/util/concurrent/RecursiveAction.java
index 48066c9..8d666f6 100644
--- a/luni/src/main/java/java/util/concurrent/RecursiveAction.java
+++ b/luni/src/main/java/java/util/concurrent/RecursiveAction.java
@@ -34,7 +34,7 @@
  *     }
  *   }
  *   // implementation details follow:
- *   final static int THRESHOLD = 1000;
+ *   static final int THRESHOLD = 1000;
  *   void sortSequentially(int lo, int hi) {
  *     Arrays.sort(array, lo, hi);
  *   }
@@ -111,21 +111,21 @@
  *     int h = hi;
  *     Applyer right = null;
  *     while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
- *        int mid = (l + h) >>> 1;
- *        right = new Applyer(array, mid, h, right);
- *        right.fork();
- *        h = mid;
+ *       int mid = (l + h) >>> 1;
+ *       right = new Applyer(array, mid, h, right);
+ *       right.fork();
+ *       h = mid;
  *     }
  *     double sum = atLeaf(l, h);
  *     while (right != null) {
- *        if (right.tryUnfork()) // directly calculate if not stolen
- *          sum += right.atLeaf(right.lo, right.hi);
+ *       if (right.tryUnfork()) // directly calculate if not stolen
+ *         sum += right.atLeaf(right.lo, right.hi);
  *       else {
- *          right.join();
- *          sum += right.result;
- *        }
- *        right = right.next;
- *      }
+ *         right.join();
+ *         sum += right.result;
+ *       }
+ *       right = right.next;
+ *     }
  *     result = sum;
  *   }
  * }}</pre>
diff --git a/luni/src/main/java/java/util/concurrent/RecursiveTask.java b/luni/src/main/java/java/util/concurrent/RecursiveTask.java
index 5e17280..421c9d3 100644
--- a/luni/src/main/java/java/util/concurrent/RecursiveTask.java
+++ b/luni/src/main/java/java/util/concurrent/RecursiveTask.java
@@ -17,7 +17,7 @@
  *   Fibonacci(int n) { this.n = n; }
  *   Integer compute() {
  *     if (n <= 1)
- *        return n;
+ *       return n;
  *     Fibonacci f1 = new Fibonacci(n - 1);
  *     f1.fork();
  *     Fibonacci f2 = new Fibonacci(n - 2);
diff --git a/luni/src/main/java/java/util/concurrent/RejectedExecutionException.java b/luni/src/main/java/java/util/concurrent/RejectedExecutionException.java
index f0005d1..c61365f 100644
--- a/luni/src/main/java/java/util/concurrent/RejectedExecutionException.java
+++ b/luni/src/main/java/java/util/concurrent/RejectedExecutionException.java
@@ -17,14 +17,14 @@
     private static final long serialVersionUID = -375805702767069545L;
 
     /**
-     * Constructs a <tt>RejectedExecutionException</tt> with no detail message.
+     * Constructs a {@code RejectedExecutionException} with no detail message.
      * The cause is not initialized, and may subsequently be
      * initialized by a call to {@link #initCause(Throwable) initCause}.
      */
     public RejectedExecutionException() { }
 
     /**
-     * Constructs a <tt>RejectedExecutionException</tt> with the
+     * Constructs a {@code RejectedExecutionException} with the
      * specified detail message. The cause is not initialized, and may
      * subsequently be initialized by a call to {@link
      * #initCause(Throwable) initCause}.
@@ -36,7 +36,7 @@
     }
 
     /**
-     * Constructs a <tt>RejectedExecutionException</tt> with the
+     * Constructs a {@code RejectedExecutionException} with the
      * specified detail message and cause.
      *
      * @param  message the detail message
@@ -48,10 +48,10 @@
     }
 
     /**
-     * Constructs a <tt>RejectedExecutionException</tt> with the
+     * Constructs a {@code RejectedExecutionException} with the
      * specified cause.  The detail message is set to {@code (cause ==
      * null ? null : cause.toString())} (which typically contains
-     * the class and detail message of <tt>cause</tt>).
+     * the class and detail message of {@code cause}).
      *
      * @param  cause the cause (which is saved for later retrieval by the
      *         {@link #getCause()} method)
diff --git a/luni/src/main/java/java/util/concurrent/RunnableFuture.java b/luni/src/main/java/java/util/concurrent/RunnableFuture.java
index 2d6d52c..ccd28e3 100644
--- a/luni/src/main/java/java/util/concurrent/RunnableFuture.java
+++ b/luni/src/main/java/java/util/concurrent/RunnableFuture.java
@@ -8,13 +8,13 @@
 
 /**
  * A {@link Future} that is {@link Runnable}. Successful execution of
- * the <tt>run</tt> method causes completion of the <tt>Future</tt>
+ * the {@code run} method causes completion of the {@code Future}
  * and allows access to its results.
  * @see FutureTask
  * @see Executor
  * @since 1.6
  * @author Doug Lea
- * @param <V> The result type returned by this Future's <tt>get</tt> method
+ * @param <V> The result type returned by this Future's {@code get} method
  */
 public interface RunnableFuture<V> extends Runnable, Future<V> {
     /**
diff --git a/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java b/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
index fbb995c..7125233 100644
--- a/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
+++ b/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
@@ -8,13 +8,13 @@
 
 /**
  * A {@link ScheduledFuture} that is {@link Runnable}. Successful
- * execution of the <tt>run</tt> method causes completion of the
- * <tt>Future</tt> and allows access to its results.
+ * execution of the {@code run} method causes completion of the
+ * {@code Future} and allows access to its results.
  * @see FutureTask
  * @see Executor
  * @since 1.6
  * @author Doug Lea
- * @param <V> The result type returned by this Future's <tt>get</tt> method
+ * @param <V> The result type returned by this Future's {@code get} method
  */
 public interface RunnableScheduledFuture<V> extends RunnableFuture<V>, ScheduledFuture<V> {
 
diff --git a/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java b/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
index 71e57ed..b978fae 100644
--- a/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
@@ -10,26 +10,26 @@
  * An {@link ExecutorService} that can schedule commands to run after a given
  * delay, or to execute periodically.
  *
- * <p> The <tt>schedule</tt> methods create tasks with various delays
+ * <p>The {@code schedule} methods create tasks with various delays
  * and return a task object that can be used to cancel or check
- * execution. The <tt>scheduleAtFixedRate</tt> and
- * <tt>scheduleWithFixedDelay</tt> methods create and execute tasks
+ * execution. The {@code scheduleAtFixedRate} and
+ * {@code scheduleWithFixedDelay} methods create and execute tasks
  * that run periodically until cancelled.
  *
- * <p> Commands submitted using the {@link Executor#execute} and
- * {@link ExecutorService} <tt>submit</tt> methods are scheduled with
+ * <p>Commands submitted using the {@link Executor#execute} and
+ * {@link ExecutorService} {@code submit} methods are scheduled with
  * a requested delay of zero. Zero and negative delays (but not
- * periods) are also allowed in <tt>schedule</tt> methods, and are
+ * periods) are also allowed in {@code schedule} methods, and are
  * treated as requests for immediate execution.
  *
- * <p>All <tt>schedule</tt> methods accept <em>relative</em> delays and
+ * <p>All {@code schedule} methods accept <em>relative</em> delays and
  * periods as arguments, not absolute times or dates. It is a simple
  * matter to transform an absolute time represented as a {@link
  * java.util.Date} to the required form. For example, to schedule at
- * a certain future <tt>date</tt>, you can use: <tt>schedule(task,
+ * a certain future {@code date}, you can use: {@code schedule(task,
  * date.getTime() - System.currentTimeMillis(),
- * TimeUnit.MILLISECONDS)</tt>. Beware however that expiration of a
- * relative delay need not coincide with the current <tt>Date</tt> at
+ * TimeUnit.MILLISECONDS)}. Beware however that expiration of a
+ * relative delay need not coincide with the current {@code Date} at
  * which the task is enabled due to network time synchronization
  * protocols, clock drift, or other factors.
  *
@@ -72,8 +72,8 @@
      * @param delay the time from now to delay execution
      * @param unit the time unit of the delay parameter
      * @return a ScheduledFuture representing pending completion of
-     *         the task and whose <tt>get()</tt> method will return
-     *         <tt>null</tt> upon completion
+     *         the task and whose {@code get()} method will return
+     *         {@code null} upon completion
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
      * @throws NullPointerException if command is null
@@ -100,8 +100,8 @@
      * Creates and executes a periodic action that becomes enabled first
      * after the given initial delay, and subsequently with the given
      * period; that is executions will commence after
-     * <tt>initialDelay</tt> then <tt>initialDelay+period</tt>, then
-     * <tt>initialDelay + 2 * period</tt>, and so on.
+     * {@code initialDelay} then {@code initialDelay+period}, then
+     * {@code initialDelay + 2 * period}, and so on.
      * If any execution of the task
      * encounters an exception, subsequent executions are suppressed.
      * Otherwise, the task will only terminate via cancellation or
@@ -114,7 +114,7 @@
      * @param period the period between successive executions
      * @param unit the time unit of the initialDelay and period parameters
      * @return a ScheduledFuture representing pending completion of
-     *         the task, and whose <tt>get()</tt> method will throw an
+     *         the task, and whose {@code get()} method will throw an
      *         exception upon cancellation
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
@@ -141,7 +141,7 @@
      * execution and the commencement of the next
      * @param unit the time unit of the initialDelay and delay parameters
      * @return a ScheduledFuture representing pending completion of
-     *         the task, and whose <tt>get()</tt> method will throw an
+     *         the task, and whose {@code get()} method will throw an
      *         exception upon cancellation
      * @throws RejectedExecutionException if the task cannot be
      *         scheduled for execution
diff --git a/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java b/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
index e41f0c3..a52351b 100644
--- a/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
+++ b/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
@@ -13,7 +13,6 @@
 
 // BEGIN android-note
 // omit class-level docs on setRemoveOnCancelPolicy()
-// removed security manager docs
 // END android-note
 
 /**
@@ -31,7 +30,7 @@
  * submission.
  *
  * <p>When a submitted task is cancelled before it is run, execution
- * is suppressed. Such a cancelled task is not
+ * is suppressed. By default, such a cancelled task is not
  * automatically removed from the work queue until its delay
  * elapses. While this enables further inspection and monitoring, it
  * may also cause unbounded retention of cancelled tasks.
@@ -54,7 +53,7 @@
  * without threads to handle tasks once they become eligible to run.
  *
  * <p><b>Extension notes:</b> This class overrides the
- * {@link ThreadPoolExecutor#execute execute} and
+ * {@link ThreadPoolExecutor#execute(Runnable) execute} and
  * {@link AbstractExecutorService#submit(Runnable) submit}
  * methods to generate internal {@link ScheduledFuture} objects to
  * control per-task delays and scheduling.  To preserve
@@ -196,7 +195,7 @@
         }
 
         /**
-         * Creates a one-shot action with given nanoTime-based trigger.
+         * Creates a one-shot action with given nanoTime-based trigger time.
          */
         ScheduledFutureTask(Callable<V> callable, long ns) {
             super(callable);
@@ -224,15 +223,14 @@
                 else
                     return 1;
             }
-            long diff = (getDelay(NANOSECONDS) -
-                         other.getDelay(NANOSECONDS));
+            long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS);
             return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
         }
 
         /**
-         * Returns true if this is a periodic (not a one-shot) action.
+         * Returns {@code true} if this is a periodic (not a one-shot) action.
          *
-         * @return true if periodic
+         * @return {@code true} if periodic
          */
         public boolean isPeriodic() {
             return period != 0;
@@ -289,7 +287,7 @@
      * is shut down, rejects the task. Otherwise adds task to queue
      * and starts a thread, if necessary, to run it.  (We cannot
      * prestart the thread to run the task because the task (probably)
-     * shouldn't be run yet,) If the pool is shut down while the task
+     * shouldn't be run yet.)  If the pool is shut down while the task
      * is being added, cancel and remove it if required by state and
      * run-after-shutdown parameters.
      *
@@ -628,7 +626,7 @@
      * {@code false} when already shutdown.
      * This value is by default {@code false}.
      *
-     * @param value if {@code true}, continue after shutdown, else don't.
+     * @param value if {@code true}, continue after shutdown, else don't
      * @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
      */
     public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
@@ -660,7 +658,7 @@
      * {@code false} when already shutdown.
      * This value is by default {@code true}.
      *
-     * @param value if {@code true}, execute after shutdown, else don't.
+     * @param value if {@code true}, execute after shutdown, else don't
      * @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
      */
     public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
@@ -834,7 +832,7 @@
         private final Condition available = lock.newCondition();
 
         /**
-         * Set f's heapIndex if it is a ScheduledFutureTask.
+         * Sets f's heapIndex if it is a ScheduledFutureTask.
          */
         private void setIndex(RunnableScheduledFuture<?> f, int idx) {
             if (f instanceof ScheduledFutureTask)
@@ -842,7 +840,7 @@
         }
 
         /**
-         * Sift element added at bottom up to its heap-ordered spot.
+         * Sifts element added at bottom up to its heap-ordered spot.
          * Call only when holding lock.
          */
         private void siftUp(int k, RunnableScheduledFuture<?> key) {
@@ -860,7 +858,7 @@
         }
 
         /**
-         * Sift element added at top down to its heap-ordered spot.
+         * Sifts element added at top down to its heap-ordered spot.
          * Call only when holding lock.
          */
         private void siftDown(int k, RunnableScheduledFuture<?> key) {
@@ -882,7 +880,7 @@
         }
 
         /**
-         * Resize the heap array.  Call only when holding lock.
+         * Resizes the heap array.  Call only when holding lock.
          */
         private void grow() {
             int oldCapacity = queue.length;
@@ -893,7 +891,7 @@
         }
 
         /**
-         * Find index of given object, or -1 if absent
+         * Finds index of given object, or -1 if absent.
          */
         private int indexOf(Object x) {
             if (x != null) {
@@ -1054,7 +1052,8 @@
                         long delay = first.getDelay(NANOSECONDS);
                         if (delay <= 0)
                             return finishPoll(first);
-                        else if (leader != null)
+                        first = null; // don't retain ref while waiting
+                        if (leader != null)
                             available.await();
                         else {
                             Thread thisThread = Thread.currentThread();
@@ -1094,6 +1093,7 @@
                             return finishPoll(first);
                         if (nanos <= 0)
                             return null;
+                        first = null; // don't retain ref while waiting
                         if (nanos < delay || leader != null)
                             nanos = available.awaitNanos(nanos);
                         else {
@@ -1134,7 +1134,7 @@
         }
 
         /**
-         * Return first element only if it is expired.
+         * Returns first element only if it is expired.
          * Used only by drainTo.  Call only when holding lock.
          */
         private RunnableScheduledFuture<?> peekExpired() {
diff --git a/luni/src/main/java/java/util/concurrent/Semaphore.java b/luni/src/main/java/java/util/concurrent/Semaphore.java
index bf2524c..9ee18a8 100644
--- a/luni/src/main/java/java/util/concurrent/Semaphore.java
+++ b/luni/src/main/java/java/util/concurrent/Semaphore.java
@@ -5,8 +5,8 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
-import java.util.concurrent.locks.*;
+import java.util.Collection;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
 
 /**
  * A counting semaphore.  Conceptually, a semaphore maintains a set of
@@ -79,13 +79,13 @@
  * exclusion lock.  This is more commonly known as a <em>binary
  * semaphore</em>, because it only has two states: one permit
  * available, or zero permits available.  When used in this way, the
- * binary semaphore has the property (unlike many {@link Lock}
+ * binary semaphore has the property (unlike many {@link java.util.concurrent.locks.Lock}
  * implementations), that the &quot;lock&quot; can be released by a
  * thread other than the owner (as semaphores have no notion of
  * ownership).  This can be useful in some specialized contexts, such
  * as deadlock recovery.
  *
- * <p> The constructor for this class optionally accepts a
+ * <p>The constructor for this class optionally accepts a
  * <em>fairness</em> parameter. When set false, this class makes no
  * guarantees about the order in which threads acquire permits. In
  * particular, <em>barging</em> is permitted, that is, a thread
@@ -123,9 +123,7 @@
  *
  * @since 1.5
  * @author Doug Lea
- *
  */
-
 public class Semaphore implements java.io.Serializable {
     private static final long serialVersionUID = -3222578661600680210L;
     /** All mechanics via AbstractQueuedSynchronizer subclass */
@@ -461,7 +459,6 @@
      *
      * @param permits the number of permits to acquire
      * @throws IllegalArgumentException if {@code permits} is negative
-     *
      */
     public void acquireUninterruptibly(int permits) {
         if (permits < 0) throw new IllegalArgumentException();
diff --git a/luni/src/main/java/java/util/concurrent/SynchronousQueue.java b/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
index b05ae0a..ea6b3d1 100644
--- a/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
+++ b/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
@@ -6,7 +6,8 @@
  */
 
 package java.util.concurrent;
-import java.util.concurrent.locks.*;
+import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.locks.ReentrantLock;
 import java.util.*;
 
 // BEGIN android-note
@@ -18,17 +19,17 @@
  * operation must wait for a corresponding remove operation by another
  * thread, and vice versa.  A synchronous queue does not have any
  * internal capacity, not even a capacity of one.  You cannot
- * <tt>peek</tt> at a synchronous queue because an element is only
+ * {@code peek} at a synchronous queue because an element is only
  * present when you try to remove it; you cannot insert an element
  * (using any method) unless another thread is trying to remove it;
  * you cannot iterate as there is nothing to iterate.  The
  * <em>head</em> of the queue is the element that the first queued
  * inserting thread is trying to add to the queue; if there is no such
  * queued thread then no element is available for removal and
- * <tt>poll()</tt> will return <tt>null</tt>.  For purposes of other
- * <tt>Collection</tt> methods (for example <tt>contains</tt>), a
- * <tt>SynchronousQueue</tt> acts as an empty collection.  This queue
- * does not permit <tt>null</tt> elements.
+ * {@code poll()} will return {@code null}.  For purposes of other
+ * {@code Collection} methods (for example {@code contains}), a
+ * {@code SynchronousQueue} acts as an empty collection.  This queue
+ * does not permit {@code null} elements.
  *
  * <p>Synchronous queues are similar to rendezvous channels used in
  * CSP and Ada. They are well suited for handoff designs, in which an
@@ -36,10 +37,10 @@
  * in another thread in order to hand it some information, event, or
  * task.
  *
- * <p> This class supports an optional fairness policy for ordering
+ * <p>This class supports an optional fairness policy for ordering
  * waiting producer and consumer threads.  By default, this ordering
  * is not guaranteed. However, a queue constructed with fairness set
- * to <tt>true</tt> grants threads access in FIFO order.
+ * to {@code true} grants threads access in FIFO order.
  *
  * <p>This class and its iterator implement all of the
  * <em>optional</em> methods of the {@link Collection} and {@link
@@ -133,7 +134,7 @@
     /**
      * Shared internal API for dual stacks and queues.
      */
-    abstract static class Transferer {
+    abstract static class Transferer<E> {
         /**
          * Performs a put or take.
          *
@@ -147,7 +148,7 @@
          *         the caller can distinguish which of these occurred
          *         by checking Thread.interrupted.
          */
-        abstract Object transfer(Object e, boolean timed, long nanos);
+        abstract E transfer(E e, boolean timed, long nanos);
     }
 
     /** The number of CPUs, for spin control */
@@ -176,7 +177,7 @@
     static final long spinForTimeoutThreshold = 1000L;
 
     /** Dual stack */
-    static final class TransferStack extends Transferer {
+    static final class TransferStack<E> extends Transferer<E> {
         /*
          * This extends Scherer-Scott dual stack algorithm, differing,
          * among other ways, by using "covering" nodes rather than
@@ -193,7 +194,7 @@
         /** Node is fulfilling another unfulfilled DATA or REQUEST */
         static final int FULFILLING = 2;
 
-        /** Return true if m has fulfilling bit set */
+        /** Returns true if m has fulfilling bit set. */
         static boolean isFulfilling(int m) { return (m & FULFILLING) != 0; }
 
         /** Node class for TransferStacks. */
@@ -292,7 +293,8 @@
         /**
          * Puts or takes an item.
          */
-        Object transfer(Object e, boolean timed, long nanos) {
+        @SuppressWarnings("unchecked")
+        E transfer(E e, boolean timed, long nanos) {
             /*
              * Basic algorithm is to loop trying one of three actions:
              *
@@ -333,7 +335,7 @@
                         }
                         if ((h = head) != null && h.next == s)
                             casHead(h, s.next);     // help s's fulfiller
-                        return (mode == REQUEST) ? m.item : s.item;
+                        return (E) ((mode == REQUEST) ? m.item : s.item);
                     }
                 } else if (!isFulfilling(h.mode)) { // try to fulfill
                     if (h.isCancelled())            // already cancelled
@@ -349,7 +351,7 @@
                             SNode mn = m.next;
                             if (m.tryMatch(s)) {
                                 casHead(s, mn);     // pop both s and m
-                                return (mode == REQUEST) ? m.item : s.item;
+                                return (E) ((mode == REQUEST) ? m.item : s.item);
                             } else                  // lost match
                                 s.casNext(m, mn);   // help unlink
                         }
@@ -400,7 +402,7 @@
              * and don't wait at all, so are trapped in transfer
              * method rather than calling awaitFulfill.
              */
-            long lastTime = timed ? System.nanoTime() : 0;
+            final long deadline = timed ? System.nanoTime() + nanos : 0L;
             Thread w = Thread.currentThread();
             int spins = (shouldSpin(s) ?
                          (timed ? maxTimedSpins : maxUntimedSpins) : 0);
@@ -411,10 +413,8 @@
                 if (m != null)
                     return m;
                 if (timed) {
-                    long now = System.nanoTime();
-                    nanos -= now - lastTime;
-                    lastTime = now;
-                    if (nanos <= 0) {
+                    nanos = deadline - System.nanoTime();
+                    if (nanos <= 0L) {
                         s.tryCancel();
                         continue;
                     }
@@ -492,7 +492,7 @@
     }
 
     /** Dual Queue */
-    static final class TransferQueue extends Transferer {
+    static final class TransferQueue<E> extends Transferer<E> {
         /*
          * This extends Scherer-Scott dual queue algorithm, differing,
          * among other ways, by using modes within nodes rather than
@@ -570,7 +570,7 @@
         /**
          * Reference to a cancelled node that might not yet have been
          * unlinked from queue because it was the last inserted node
-         * when it cancelled.
+         * when it was cancelled.
          */
         transient volatile QNode cleanMe;
 
@@ -609,7 +609,8 @@
         /**
          * Puts or takes an item.
          */
-        Object transfer(Object e, boolean timed, long nanos) {
+        @SuppressWarnings("unchecked")
+        E transfer(E e, boolean timed, long nanos) {
             /* Basic algorithm is to loop trying to take either of
              * two actions:
              *
@@ -672,7 +673,7 @@
                             s.item = s;
                         s.waiter = null;
                     }
-                    return (x != null) ? x : e;
+                    return (x != null) ? (E)x : e;
 
                 } else {                            // complementary-mode
                     QNode m = h.next;               // node to fulfill
@@ -689,7 +690,7 @@
 
                     advanceHead(h, m);              // successfully fulfilled
                     LockSupport.unpark(m.waiter);
-                    return (x != null) ? x : e;
+                    return (x != null) ? (E)x : e;
                 }
             }
         }
@@ -703,9 +704,9 @@
          * @param nanos timeout value
          * @return matched item, or s if cancelled
          */
-        Object awaitFulfill(QNode s, Object e, boolean timed, long nanos) {
+        Object awaitFulfill(QNode s, E e, boolean timed, long nanos) {
             /* Same idea as TransferStack.awaitFulfill */
-            long lastTime = timed ? System.nanoTime() : 0;
+            final long deadline = timed ? System.nanoTime() + nanos : 0L;
             Thread w = Thread.currentThread();
             int spins = ((head.next == s) ?
                          (timed ? maxTimedSpins : maxUntimedSpins) : 0);
@@ -716,10 +717,8 @@
                 if (x != e)
                     return x;
                 if (timed) {
-                    long now = System.nanoTime();
-                    nanos -= now - lastTime;
-                    lastTime = now;
-                    if (nanos <= 0) {
+                    nanos = deadline - System.nanoTime();
+                    if (nanos <= 0L) {
                         s.tryCancel(e);
                         continue;
                     }
@@ -816,23 +815,23 @@
      * isn't a noticeable performance penalty for using volatile
      * instead of final here.
      */
-    private transient volatile Transferer transferer;
+    private transient volatile Transferer<E> transferer;
 
     /**
-     * Creates a <tt>SynchronousQueue</tt> with nonfair access policy.
+     * Creates a {@code SynchronousQueue} with nonfair access policy.
      */
     public SynchronousQueue() {
         this(false);
     }
 
     /**
-     * Creates a <tt>SynchronousQueue</tt> with the specified fairness policy.
+     * Creates a {@code SynchronousQueue} with the specified fairness policy.
      *
      * @param fair if true, waiting threads contend in FIFO order for
      *        access; otherwise the order is unspecified.
      */
     public SynchronousQueue(boolean fair) {
-        transferer = fair ? new TransferQueue() : new TransferStack();
+        transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
     }
 
     /**
@@ -842,9 +841,9 @@
      * @throws InterruptedException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
      */
-    public void put(E o) throws InterruptedException {
-        if (o == null) throw new NullPointerException();
-        if (transferer.transfer(o, false, 0) == null) {
+    public void put(E e) throws InterruptedException {
+        if (e == null) throw new NullPointerException();
+        if (transferer.transfer(e, false, 0) == null) {
             Thread.interrupted();
             throw new InterruptedException();
         }
@@ -854,15 +853,15 @@
      * Inserts the specified element into this queue, waiting if necessary
      * up to the specified wait time for another thread to receive it.
      *
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if the
-     *         specified waiting time elapses before a consumer appears.
+     * @return {@code true} if successful, or {@code false} if the
+     *         specified waiting time elapses before a consumer appears
      * @throws InterruptedException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
      */
-    public boolean offer(E o, long timeout, TimeUnit unit)
+    public boolean offer(E e, long timeout, TimeUnit unit)
         throws InterruptedException {
-        if (o == null) throw new NullPointerException();
-        if (transferer.transfer(o, true, unit.toNanos(timeout)) != null)
+        if (e == null) throw new NullPointerException();
+        if (transferer.transfer(e, true, unit.toNanos(timeout)) != null)
             return true;
         if (!Thread.interrupted())
             return false;
@@ -874,8 +873,8 @@
      * waiting to receive it.
      *
      * @param e the element to add
-     * @return <tt>true</tt> if the element was added to this queue, else
-     *         <tt>false</tt>
+     * @return {@code true} if the element was added to this queue, else
+     *         {@code false}
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
@@ -891,9 +890,9 @@
      * @throws InterruptedException {@inheritDoc}
      */
     public E take() throws InterruptedException {
-        Object e = transferer.transfer(null, false, 0);
+        E e = transferer.transfer(null, false, 0);
         if (e != null)
-            return (E)e;
+            return e;
         Thread.interrupted();
         throw new InterruptedException();
     }
@@ -903,14 +902,14 @@
      * if necessary up to the specified wait time, for another thread
      * to insert it.
      *
-     * @return the head of this queue, or <tt>null</tt> if the
-     *         specified waiting time elapses before an element is present.
+     * @return the head of this queue, or {@code null} if the
+     *         specified waiting time elapses before an element is present
      * @throws InterruptedException {@inheritDoc}
      */
     public E poll(long timeout, TimeUnit unit) throws InterruptedException {
-        Object e = transferer.transfer(null, true, unit.toNanos(timeout));
+        E e = transferer.transfer(null, true, unit.toNanos(timeout));
         if (e != null || !Thread.interrupted())
-            return (E)e;
+            return e;
         throw new InterruptedException();
     }
 
@@ -918,18 +917,18 @@
      * Retrieves and removes the head of this queue, if another thread
      * is currently making an element available.
      *
-     * @return the head of this queue, or <tt>null</tt> if no
-     *         element is available.
+     * @return the head of this queue, or {@code null} if no
+     *         element is available
      */
     public E poll() {
-        return (E)transferer.transfer(null, true, 0);
+        return transferer.transfer(null, true, 0);
     }
 
     /**
-     * Always returns <tt>true</tt>.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Always returns {@code true}.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
-     * @return <tt>true</tt>
+     * @return {@code true}
      */
     public boolean isEmpty() {
         return true;
@@ -937,9 +936,9 @@
 
     /**
      * Always returns zero.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
-     * @return zero.
+     * @return zero
      */
     public int size() {
         return 0;
@@ -947,9 +946,9 @@
 
     /**
      * Always returns zero.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
-     * @return zero.
+     * @return zero
      */
     public int remainingCapacity() {
         return 0;
@@ -957,80 +956,80 @@
 
     /**
      * Does nothing.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * A {@code SynchronousQueue} has no internal capacity.
      */
     public void clear() {
     }
 
     /**
-     * Always returns <tt>false</tt>.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Always returns {@code false}.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
      * @param o the element
-     * @return <tt>false</tt>
+     * @return {@code false}
      */
     public boolean contains(Object o) {
         return false;
     }
 
     /**
-     * Always returns <tt>false</tt>.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Always returns {@code false}.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
      * @param o the element to remove
-     * @return <tt>false</tt>
+     * @return {@code false}
      */
     public boolean remove(Object o) {
         return false;
     }
 
     /**
-     * Returns <tt>false</tt> unless the given collection is empty.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Returns {@code false} unless the given collection is empty.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
      * @param c the collection
-     * @return <tt>false</tt> unless given collection is empty
+     * @return {@code false} unless given collection is empty
      */
     public boolean containsAll(Collection<?> c) {
         return c.isEmpty();
     }
 
     /**
-     * Always returns <tt>false</tt>.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Always returns {@code false}.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
      * @param c the collection
-     * @return <tt>false</tt>
+     * @return {@code false}
      */
     public boolean removeAll(Collection<?> c) {
         return false;
     }
 
     /**
-     * Always returns <tt>false</tt>.
-     * A <tt>SynchronousQueue</tt> has no internal capacity.
+     * Always returns {@code false}.
+     * A {@code SynchronousQueue} has no internal capacity.
      *
      * @param c the collection
-     * @return <tt>false</tt>
+     * @return {@code false}
      */
     public boolean retainAll(Collection<?> c) {
         return false;
     }
 
     /**
-     * Always returns <tt>null</tt>.
-     * A <tt>SynchronousQueue</tt> does not return elements
+     * Always returns {@code null}.
+     * A {@code SynchronousQueue} does not return elements
      * unless actively waited on.
      *
-     * @return <tt>null</tt>
+     * @return {@code null}
      */
     public E peek() {
         return null;
     }
 
     /**
-     * Returns an empty iterator in which <tt>hasNext</tt> always returns
-     * <tt>false</tt>.
+     * Returns an empty iterator in which {@code hasNext} always returns
+     * {@code false}.
      *
      * @return an empty iterator
      */
@@ -1058,7 +1057,7 @@
     }
 
     /**
-     * Sets the zeroeth element of the specified array to <tt>null</tt>
+     * Sets the zeroeth element of the specified array to {@code null}
      * (if the array has non-zero length) and returns it.
      *
      * @param a the array
@@ -1117,6 +1116,7 @@
      * object is ever serialized or deserialized.
      */
 
+    @SuppressWarnings("serial")
     static class WaitQueue implements java.io.Serializable { }
     static class LifoWaitQueue extends WaitQueue {
         private static final long serialVersionUID = -3633113410248163686L;
@@ -1129,9 +1129,7 @@
     private WaitQueue waitingConsumers;
 
     /**
-     * Saves the state to a stream (that is, serializes it).
-     *
-     * @param s the stream
+     * Saves this queue to a stream (that is, serializes it).
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
@@ -1149,13 +1147,16 @@
         s.defaultWriteObject();
     }
 
+    /**
+     * Reconstitutes this queue from a stream (that is, deserializes it).
+     */
     private void readObject(final java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         s.defaultReadObject();
         if (waitingProducers instanceof FifoWaitQueue)
-            transferer = new TransferQueue();
+            transferer = new TransferQueue<E>();
         else
-            transferer = new TransferStack();
+            transferer = new TransferStack<E>();
     }
 
     // Unsafe mechanics
diff --git a/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java b/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
index 331e225..9586293 100644
--- a/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
+++ b/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
@@ -5,8 +5,10 @@
  */
 
 package java.util.concurrent;
-import java.util.concurrent.locks.*;
-import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.*;
 
 // BEGIN android-note
@@ -48,22 +50,23 @@
  * corePoolSize (see {@link #getCorePoolSize}) and
  * maximumPoolSize (see {@link #getMaximumPoolSize}).
  *
- * When a new task is submitted in method {@link #execute}, and fewer
- * than corePoolSize threads are running, a new thread is created to
- * handle the request, even if other worker threads are idle.  If
- * there are more than corePoolSize but less than maximumPoolSize
- * threads running, a new thread will be created only if the queue is
- * full.  By setting corePoolSize and maximumPoolSize the same, you
- * create a fixed-size thread pool. By setting maximumPoolSize to an
- * essentially unbounded value such as {@code Integer.MAX_VALUE}, you
- * allow the pool to accommodate an arbitrary number of concurrent
- * tasks. Most typically, core and maximum pool sizes are set only
- * upon construction, but they may also be changed dynamically using
- * {@link #setCorePoolSize} and {@link #setMaximumPoolSize}. </dd>
+ * When a new task is submitted in method {@link #execute(Runnable)},
+ * and fewer than corePoolSize threads are running, a new thread is
+ * created to handle the request, even if other worker threads are
+ * idle.  If there are more than corePoolSize but less than
+ * maximumPoolSize threads running, a new thread will be created only
+ * if the queue is full.  By setting corePoolSize and maximumPoolSize
+ * the same, you create a fixed-size thread pool. By setting
+ * maximumPoolSize to an essentially unbounded value such as {@code
+ * Integer.MAX_VALUE}, you allow the pool to accommodate an arbitrary
+ * number of concurrent tasks. Most typically, core and maximum pool
+ * sizes are set only upon construction, but they may also be changed
+ * dynamically using {@link #setCorePoolSize} and {@link
+ * #setMaximumPoolSize}. </dd>
  *
  * <dt>On-demand construction</dt>
  *
- * <dd> By default, even core threads are initially created and
+ * <dd>By default, even core threads are initially created and
  * started only when new tasks arrive, but this can be overridden
  * dynamically using method {@link #prestartCoreThread} or {@link
  * #prestartAllCoreThreads}.  You probably want to prestart threads if
@@ -85,17 +88,17 @@
  *
  * <dd>If the pool currently has more than corePoolSize threads,
  * excess threads will be terminated if they have been idle for more
- * than the keepAliveTime (see {@link #getKeepAliveTime}). This
- * provides a means of reducing resource consumption when the pool is
- * not being actively used. If the pool becomes more active later, new
- * threads will be constructed. This parameter can also be changed
- * dynamically using method {@link #setKeepAliveTime}. Using a value
- * of {@code Long.MAX_VALUE} {@link TimeUnit#NANOSECONDS} effectively
- * disables idle threads from ever terminating prior to shut down. By
- * default, the keep-alive policy applies only when there are more
- * than corePoolSizeThreads. But method {@link
- * #allowCoreThreadTimeOut(boolean)} can be used to apply this
- * time-out policy to core threads as well, so long as the
+ * than the keepAliveTime (see {@link #getKeepAliveTime(TimeUnit)}).
+ * This provides a means of reducing resource consumption when the
+ * pool is not being actively used. If the pool becomes more active
+ * later, new threads will be constructed. This parameter can also be
+ * changed dynamically using method {@link #setKeepAliveTime(long,
+ * TimeUnit)}.  Using a value of {@code Long.MAX_VALUE} {@link
+ * TimeUnit#NANOSECONDS} effectively disables idle threads from ever
+ * terminating prior to shut down. By default, the keep-alive policy
+ * applies only when there are more than corePoolSize threads. But
+ * method {@link #allowCoreThreadTimeOut(boolean)} can be used to
+ * apply this time-out policy to core threads as well, so long as the
  * keepAliveTime value is non-zero. </dd>
  *
  * <dt>Queuing</dt>
@@ -165,14 +168,14 @@
  *
  * <dt>Rejected tasks</dt>
  *
- * <dd> New tasks submitted in method {@link #execute} will be
- * <em>rejected</em> when the Executor has been shut down, and also
- * when the Executor uses finite bounds for both maximum threads and
- * work queue capacity, and is saturated.  In either case, the {@code
- * execute} method invokes the {@link
- * RejectedExecutionHandler#rejectedExecution} method of its {@link
- * RejectedExecutionHandler}.  Four predefined handler policies are
- * provided:
+ * <dd>New tasks submitted in method {@link #execute(Runnable)} will be
+ * <em>rejected</em> when the Executor has been shut down, and also when
+ * the Executor uses finite bounds for both maximum threads and work queue
+ * capacity, and is saturated.  In either case, the {@code execute} method
+ * invokes the {@link
+ * RejectedExecutionHandler#rejectedExecution(Runnable, ThreadPoolExecutor)}
+ * method of its {@link RejectedExecutionHandler}.  Four predefined handler
+ * policies are provided:
  *
  * <ol>
  *
@@ -202,30 +205,31 @@
  *
  * <dt>Hook methods</dt>
  *
- * <dd>This class provides {@code protected} overridable {@link
- * #beforeExecute} and {@link #afterExecute} methods that are called
+ * <dd>This class provides {@code protected} overridable
+ * {@link #beforeExecute(Thread, Runnable)} and
+ * {@link #afterExecute(Runnable, Throwable)} methods that are called
  * before and after execution of each task.  These can be used to
  * manipulate the execution environment; for example, reinitializing
- * ThreadLocals, gathering statistics, or adding log
- * entries. Additionally, method {@link #terminated} can be overridden
- * to perform any special processing that needs to be done once the
- * Executor has fully terminated.
+ * ThreadLocals, gathering statistics, or adding log entries.
+ * Additionally, method {@link #terminated} can be overridden to perform
+ * any special processing that needs to be done once the Executor has
+ * fully terminated.
  *
  * <p>If hook or callback methods throw exceptions, internal worker
  * threads may in turn fail and abruptly terminate.</dd>
  *
  * <dt>Queue maintenance</dt>
  *
- * <dd> Method {@link #getQueue} allows access to the work queue for
- * purposes of monitoring and debugging.  Use of this method for any
- * other purpose is strongly discouraged.  Two supplied methods,
- * {@link #remove} and {@link #purge} are available to assist in
- * storage reclamation when large numbers of queued tasks become
- * cancelled.</dd>
+ * <dd>Method {@link #getQueue()} allows access to the work queue
+ * for purposes of monitoring and debugging.  Use of this method for
+ * any other purpose is strongly discouraged.  Two supplied methods,
+ * {@link #remove(Runnable)} and {@link #purge} are available to
+ * assist in storage reclamation when large numbers of queued tasks
+ * become cancelled.</dd>
  *
  * <dt>Finalization</dt>
  *
- * <dd> A pool that is no longer referenced in a program <em>AND</em>
+ * <dd>A pool that is no longer referenced in a program <em>AND</em>
  * has no remaining threads will be {@code shutdown} automatically. If
  * you would like to ensure that unreferenced pools are reclaimed even
  * if users forget to call {@link #shutdown}, then you must arrange
@@ -235,7 +239,7 @@
  *
  * </dl>
  *
- * <p> <b>Extension example</b>. Most extensions of this class
+ * <p><b>Extension example</b>. Most extensions of this class
  * override one or more of the protected hook methods. For example,
  * here is a subclass that adds a simple pause/resume feature:
  *
@@ -304,7 +308,7 @@
      * bookkeeping before terminating. The user-visible pool size is
      * reported as the current size of the workers set.
      *
-     * The runState provides the main lifecyle control, taking on values:
+     * The runState provides the main lifecycle control, taking on values:
      *
      *   RUNNING:  Accept new tasks and process queued tasks
      *   SHUTDOWN: Don't accept new tasks, but process queued tasks
@@ -374,14 +378,14 @@
     }
 
     /**
-     * Attempt to CAS-increment the workerCount field of ctl.
+     * Attempts to CAS-increment the workerCount field of ctl.
      */
     private boolean compareAndIncrementWorkerCount(int expect) {
         return ctl.compareAndSet(expect, expect + 1);
     }
 
     /**
-     * Attempt to CAS-decrement the workerCount field of ctl.
+     * Attempts to CAS-decrement the workerCount field of ctl.
      */
     private boolean compareAndDecrementWorkerCount(int expect) {
         return ctl.compareAndSet(expect, expect - 1);
@@ -461,10 +465,15 @@
      * policy limiting the number of threads.  Even though it is not
      * treated as an error, failure to create threads may result in
      * new tasks being rejected or existing ones remaining stuck in
-     * the queue. On the other hand, no special precautions exist to
-     * handle OutOfMemoryErrors that might be thrown while trying to
-     * create threads, since there is generally no recourse from
-     * within this class.
+     * the queue.
+     *
+     * We go further and preserve pool invariants even in the face of
+     * errors such as OutOfMemoryError, that might be thrown while
+     * trying to create threads.  Such errors are rather common due to
+     * the need to allocate a native stack in Thread.start, and users
+     * will want to perform clean pool shutdown to clean up.  There
+     * will likely be enough memory available for the cleanup code to
+     * complete without encountering yet another OutOfMemoryError.
      */
     private volatile ThreadFactory threadFactory;
 
@@ -538,9 +547,13 @@
      * task execution.  This protects against interrupts that are
      * intended to wake up a worker thread waiting for a task from
      * instead interrupting a task being run.  We implement a simple
-     * non-reentrant mutual exclusion lock rather than use ReentrantLock
-     * because we do not want worker tasks to be able to reacquire the
-     * lock when they invoke pool control methods like setCorePoolSize.
+     * non-reentrant mutual exclusion lock rather than use
+     * ReentrantLock because we do not want worker tasks to be able to
+     * reacquire the lock when they invoke pool control methods like
+     * setCorePoolSize.  Additionally, to suppress interrupts until
+     * the thread actually starts running tasks, we initialize lock
+     * state to a negative value, and clear it upon start (in
+     * runWorker).
      */
     private final class Worker
         extends AbstractQueuedSynchronizer
@@ -564,6 +577,7 @@
          * @param firstTask the first task (null if none)
          */
         Worker(Runnable firstTask) {
+            setState(-1); // inhibit interrupts until runWorker
             this.firstTask = firstTask;
             this.thread = getThreadFactory().newThread(this);
         }
@@ -579,7 +593,7 @@
         // The value 1 represents the locked state.
 
         protected boolean isHeldExclusively() {
-            return getState() == 1;
+            return getState() != 0;
         }
 
         protected boolean tryAcquire(int unused) {
@@ -600,6 +614,16 @@
         public boolean tryLock()  { return tryAcquire(1); }
         public void unlock()      { release(1); }
         public boolean isLocked() { return isHeldExclusively(); }
+
+        void interruptIfStarted() {
+            Thread t;
+            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
+                try {
+                    t.interrupt();
+                } catch (SecurityException ignore) {
+                }
+            }
+        }
     }
 
     /*
@@ -698,12 +722,8 @@
         final ReentrantLock mainLock = this.mainLock;
         mainLock.lock();
         try {
-            for (Worker w : workers) {
-                try {
-                    w.thread.interrupt();
-                } catch (SecurityException ignore) {
-                }
-            }
+            for (Worker w : workers)
+                w.interruptIfStarted();
         } finally {
             mainLock.unlock();
         }
@@ -760,19 +780,6 @@
 
     private static final boolean ONLY_ONE = true;
 
-    /**
-     * Ensures that unless the pool is stopping, the current thread
-     * does not have its interrupt set. This requires a double-check
-     * of state in case the interrupt was cleared concurrently with a
-     * shutdownNow -- if so, the interrupt is re-enabled.
-     */
-    private void clearInterruptsForTaskRun() {
-        if (runStateLessThan(ctl.get(), STOP) &&
-            Thread.interrupted() &&
-            runStateAtLeast(ctl.get(), STOP))
-            Thread.currentThread().interrupt();
-    }
-
     /*
      * Misc utilities, most of which are also exported to
      * ScheduledThreadPoolExecutor
@@ -813,7 +820,7 @@
      */
     private List<Runnable> drainQueue() {
         BlockingQueue<Runnable> q = workQueue;
-        List<Runnable> taskList = new ArrayList<Runnable>();
+        ArrayList<Runnable> taskList = new ArrayList<Runnable>();
         q.drainTo(taskList);
         if (!q.isEmpty()) {
             for (Runnable r : q.toArray(new Runnable[0])) {
@@ -832,12 +839,13 @@
      * Checks if a new worker can be added with respect to current
      * pool state and the given bound (either core or maximum). If so,
      * the worker count is adjusted accordingly, and, if possible, a
-     * new worker is created and started running firstTask as its
+     * new worker is created and started, running firstTask as its
      * first task. This method returns false if the pool is stopped or
      * eligible to shut down. It also returns false if the thread
-     * factory fails to create a thread when asked, which requires a
-     * backout of workerCount, and a recheck for termination, in case
-     * the existence of this worker was holding up termination.
+     * factory fails to create a thread when asked.  If the thread
+     * creation fails, either due to the thread factory returning
+     * null, or due to an exception (typically OutOfMemoryError in
+     * Thread.start()), we roll back cleanly.
      *
      * @param firstTask the task the new thread should run first (or
      * null if none). Workers are created with an initial first task
@@ -880,46 +888,64 @@
             }
         }
 
-        Worker w = new Worker(firstTask);
-        Thread t = w.thread;
+        boolean workerStarted = false;
+        boolean workerAdded = false;
+        Worker w = null;
+        try {
+            w = new Worker(firstTask);
+            final Thread t = w.thread;
+            if (t != null) {
+                final ReentrantLock mainLock = this.mainLock;
+                mainLock.lock();
+                try {
+                    // Recheck while holding lock.
+                    // Back out on ThreadFactory failure or if
+                    // shut down before lock acquired.
+                    int rs = runStateOf(ctl.get());
 
+                    if (rs < SHUTDOWN ||
+                        (rs == SHUTDOWN && firstTask == null)) {
+                        if (t.isAlive()) // precheck that t is startable
+                            throw new IllegalThreadStateException();
+                        workers.add(w);
+                        int s = workers.size();
+                        if (s > largestPoolSize)
+                            largestPoolSize = s;
+                        workerAdded = true;
+                    }
+                } finally {
+                    mainLock.unlock();
+                }
+                if (workerAdded) {
+                    t.start();
+                    workerStarted = true;
+                }
+            }
+        } finally {
+            if (! workerStarted)
+                addWorkerFailed(w);
+        }
+        return workerStarted;
+    }
+
+    /**
+     * Rolls back the worker thread creation.
+     * - removes worker from workers, if present
+     * - decrements worker count
+     * - rechecks for termination, in case the existence of this
+     *   worker was holding up termination
+     */
+    private void addWorkerFailed(Worker w) {
         final ReentrantLock mainLock = this.mainLock;
         mainLock.lock();
         try {
-            // Recheck while holding lock.
-            // Back out on ThreadFactory failure or if
-            // shut down before lock acquired.
-            int c = ctl.get();
-            int rs = runStateOf(c);
-
-            if (t == null ||
-                (rs >= SHUTDOWN &&
-                 ! (rs == SHUTDOWN &&
-                    firstTask == null))) {
-                decrementWorkerCount();
-                tryTerminate();
-                return false;
-            }
-
-            workers.add(w);
-
-            int s = workers.size();
-            if (s > largestPoolSize)
-                largestPoolSize = s;
+            if (w != null)
+                workers.remove(w);
+            decrementWorkerCount();
+            tryTerminate();
         } finally {
             mainLock.unlock();
         }
-
-        t.start();
-        // It is possible (but unlikely) for a thread to have been
-        // added to workers, but not yet started, during transition to
-        // STOP, which could result in a rare missed interrupt,
-        // because Thread.interrupt is not guaranteed to have any effect
-        // on a non-yet-started Thread (see Thread#interrupt).
-        if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted())
-            t.interrupt();
-
-        return true;
     }
 
     /**
@@ -974,7 +1000,8 @@
      * 4. This worker timed out waiting for a task, and timed-out
      *    workers are subject to termination (that is,
      *    {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
-     *    both before and after the timed wait.
+     *    both before and after the timed wait, and if the queue is
+     *    non-empty, this worker is not the last thread in the pool.
      *
      * @return task, or null if the worker must exit, in which case
      *         workerCount is decremented
@@ -982,7 +1009,6 @@
     private Runnable getTask() {
         boolean timedOut = false; // Did the last poll() time out?
 
-        retry:
         for (;;) {
             int c = ctl.get();
             int rs = runStateOf(c);
@@ -993,20 +1019,16 @@
                 return null;
             }
 
-            boolean timed;      // Are workers subject to culling?
+            int wc = workerCountOf(c);
 
-            for (;;) {
-                int wc = workerCountOf(c);
-                timed = allowCoreThreadTimeOut || wc > corePoolSize;
+            // Are workers subject to culling?
+            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
 
-                if (wc <= maximumPoolSize && ! (timedOut && timed))
-                    break;
+            if ((wc > maximumPoolSize || (timed && timedOut))
+                && (wc > 1 || workQueue.isEmpty())) {
                 if (compareAndDecrementWorkerCount(c))
                     return null;
-                c = ctl.get();  // Re-read ctl
-                if (runStateOf(c) != rs)
-                    continue retry;
-                // else CAS failed due to workerCount change; retry inner loop
+                continue;
             }
 
             try {
@@ -1035,9 +1057,9 @@
      * usually leads processWorkerExit to replace this thread.
      *
      * 2. Before running any task, the lock is acquired to prevent
-     * other pool interrupts while the task is executing, and
-     * clearInterruptsForTaskRun called to ensure that unless pool is
-     * stopping, this thread does not have its interrupt set.
+     * other pool interrupts while the task is executing, and then we
+     * ensure that unless pool is stopping, this thread does not have
+     * its interrupt set.
      *
      * 3. Each task run is preceded by a call to beforeExecute, which
      * might throw an exception, in which case we cause thread to die
@@ -1045,12 +1067,12 @@
      * the task.
      *
      * 4. Assuming beforeExecute completes normally, we run the task,
-     * gathering any of its thrown exceptions to send to
-     * afterExecute. We separately handle RuntimeException, Error
-     * (both of which the specs guarantee that we trap) and arbitrary
-     * Throwables.  Because we cannot rethrow Throwables within
-     * Runnable.run, we wrap them within Errors on the way out (to the
-     * thread's UncaughtExceptionHandler).  Any thrown exception also
+     * gathering any of its thrown exceptions to send to afterExecute.
+     * We separately handle RuntimeException, Error (both of which the
+     * specs guarantee that we trap) and arbitrary Throwables.
+     * Because we cannot rethrow Throwables within Runnable.run, we
+     * wrap them within Errors on the way out (to the thread's
+     * UncaughtExceptionHandler).  Any thrown exception also
      * conservatively causes thread to die.
      *
      * 5. After task.run completes, we call afterExecute, which may
@@ -1066,15 +1088,25 @@
      * @param w the worker
      */
     final void runWorker(Worker w) {
+        Thread wt = Thread.currentThread();
         Runnable task = w.firstTask;
         w.firstTask = null;
+        w.unlock(); // allow interrupts
         boolean completedAbruptly = true;
         try {
             while (task != null || (task = getTask()) != null) {
                 w.lock();
-                clearInterruptsForTaskRun();
+                // If pool is stopping, ensure thread is interrupted;
+                // if not, ensure thread is not interrupted.  This
+                // requires a recheck in second case to deal with
+                // shutdownNow race while clearing interrupt
+                if ((runStateAtLeast(ctl.get(), STOP) ||
+                     (Thread.interrupted() &&
+                      runStateAtLeast(ctl.get(), STOP))) &&
+                    !wt.isInterrupted())
+                    wt.interrupt();
                 try {
-                    beforeExecute(w.thread, task);
+                    beforeExecute(wt, task);
                     Throwable thrown = null;
                     try {
                         task.run();
@@ -1374,7 +1406,7 @@
      * ignored or suppressed interruption, causing this executor not
      * to properly terminate.
      *
-     * @return true if terminating but not yet terminated
+     * @return {@code true} if terminating but not yet terminated
      */
     public boolean isTerminating() {
         int c = ctl.get();
@@ -1428,7 +1460,7 @@
      * Returns the thread factory used to create new threads.
      *
      * @return the current thread factory
-     * @see #setThreadFactory
+     * @see #setThreadFactory(ThreadFactory)
      */
     public ThreadFactory getThreadFactory() {
         return threadFactory;
@@ -1451,7 +1483,7 @@
      * Returns the current handler for unexecutable tasks.
      *
      * @return the current handler
-     * @see #setRejectedExecutionHandler
+     * @see #setRejectedExecutionHandler(RejectedExecutionHandler)
      */
     public RejectedExecutionHandler getRejectedExecutionHandler() {
         return handler;
@@ -1623,7 +1655,7 @@
      * @param unit the time unit of the {@code time} argument
      * @throws IllegalArgumentException if {@code time} less than zero or
      *         if {@code time} is zero and {@code allowsCoreThreadTimeOut}
-     * @see #getKeepAliveTime
+     * @see #getKeepAliveTime(TimeUnit)
      */
     public void setKeepAliveTime(long time, TimeUnit unit) {
         if (time < 0)
@@ -1644,7 +1676,7 @@
      *
      * @param unit the desired time unit of the result
      * @return the time limit
-     * @see #setKeepAliveTime
+     * @see #setKeepAliveTime(long, TimeUnit)
      */
     public long getKeepAliveTime(TimeUnit unit) {
         return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
@@ -1669,7 +1701,7 @@
      * present, thus causing it not to be run if it has not already
      * started.
      *
-     * <p> This method may be useful as one part of a cancellation
+     * <p>This method may be useful as one part of a cancellation
      * scheme.  It may fail to remove tasks that have been converted
      * into other forms before being placed on the internal queue. For
      * example, a task entered using {@code submit} might be
@@ -1678,7 +1710,7 @@
      * remove those Futures that have been cancelled.
      *
      * @param task the task to remove
-     * @return true if the task was removed
+     * @return {@code true} if the task was removed
      */
     public boolean remove(Runnable task) {
         boolean removed = workQueue.remove(task);
@@ -1973,7 +2005,7 @@
          *
          * @param r the runnable task requested to be executed
          * @param e the executor attempting to execute this task
-         * @throws RejectedExecutionException always.
+         * @throws RejectedExecutionException always
          */
         public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
             throw new RejectedExecutionException("Task " + r.toString() +
diff --git a/luni/src/main/java/java/util/concurrent/TimeUnit.java b/luni/src/main/java/java/util/concurrent/TimeUnit.java
index 50f6ce0..eb2c495 100644
--- a/luni/src/main/java/java/util/concurrent/TimeUnit.java
+++ b/luni/src/main/java/java/util/concurrent/TimeUnit.java
@@ -7,10 +7,10 @@
 package java.util.concurrent;
 
 /**
- * A <tt>TimeUnit</tt> represents time durations at a given unit of
+ * A {@code TimeUnit} represents time durations at a given unit of
  * granularity and provides utility methods to convert across units,
  * and to perform timing and delay operations in these units.  A
- * <tt>TimeUnit</tt> does not maintain time information, but only
+ * {@code TimeUnit} does not maintain time information, but only
  * helps organize and use time representations that may be maintained
  * separately across various contexts.  A nanosecond is defined as one
  * thousandth of a microsecond, a microsecond as one thousandth of a
@@ -18,7 +18,7 @@
  * as sixty seconds, an hour as sixty minutes, and a day as twenty four
  * hours.
  *
- * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
+ * <p>A {@code TimeUnit} is mainly used to inform time-based methods
  * how a given timing parameter should be interpreted. For example,
  * the following code will timeout in 50 milliseconds if the {@link
  * java.util.concurrent.locks.Lock lock} is not available:
@@ -34,7 +34,7 @@
  *
  * Note however, that there is no guarantee that a particular timeout
  * implementation will be able to notice the passage of time at the
- * same granularity as the given <tt>TimeUnit</tt>.
+ * same granularity as the given {@code TimeUnit}.
  *
  * @since 1.5
  * @author Doug Lea
@@ -148,31 +148,31 @@
      * Convert the given time duration in the given unit to this
      * unit.  Conversions from finer to coarser granularities
      * truncate, so lose precision. For example converting
-     * <tt>999</tt> milliseconds to seconds results in
-     * <tt>0</tt>. Conversions from coarser to finer granularities
+     * {@code 999} milliseconds to seconds results in
+     * {@code 0}. Conversions from coarser to finer granularities
      * with arguments that would numerically overflow saturate to
-     * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
+     * {@code Long.MIN_VALUE} if negative or {@code Long.MAX_VALUE}
      * if positive.
      *
      * <p>For example, to convert 10 minutes to milliseconds, use:
-     * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
+     * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
      *
-     * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
-     * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
+     * @param sourceDuration the time duration in the given {@code sourceUnit}
+     * @param sourceUnit the unit of the {@code sourceDuration} argument
      * @return the converted duration in this unit,
-     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
-     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * or {@code Long.MIN_VALUE} if conversion would negatively
+     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
      */
     public long convert(long sourceDuration, TimeUnit sourceUnit) {
         throw new AbstractMethodError();
     }
 
     /**
-     * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
+     * Equivalent to {@code NANOSECONDS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
-     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * or {@code Long.MIN_VALUE} if conversion would negatively
+     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
      * @see #convert
      */
     public long toNanos(long duration) {
@@ -180,11 +180,11 @@
     }
 
     /**
-     * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
+     * Equivalent to {@code MICROSECONDS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
-     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * or {@code Long.MIN_VALUE} if conversion would negatively
+     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
      * @see #convert
      */
     public long toMicros(long duration) {
@@ -192,11 +192,11 @@
     }
 
     /**
-     * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
+     * Equivalent to {@code MILLISECONDS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
-     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * or {@code Long.MIN_VALUE} if conversion would negatively
+     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
      * @see #convert
      */
     public long toMillis(long duration) {
@@ -204,11 +204,11 @@
     }
 
     /**
-     * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
+     * Equivalent to {@code SECONDS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
-     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * or {@code Long.MIN_VALUE} if conversion would negatively
+     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
      * @see #convert
      */
     public long toSeconds(long duration) {
@@ -216,11 +216,11 @@
     }
 
     /**
-     * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
+     * Equivalent to {@code MINUTES.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
-     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * or {@code Long.MIN_VALUE} if conversion would negatively
+     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
      * @see #convert
      * @since 1.6
      */
@@ -229,11 +229,11 @@
     }
 
     /**
-     * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
+     * Equivalent to {@code HOURS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration,
-     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
-     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * or {@code Long.MIN_VALUE} if conversion would negatively
+     * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
      * @see #convert
      * @since 1.6
      */
@@ -242,7 +242,7 @@
     }
 
     /**
-     * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
+     * Equivalent to {@code DAYS.convert(duration, this)}.
      * @param duration the duration
      * @return the converted duration
      * @see #convert
@@ -265,9 +265,9 @@
      * Performs a timed {@link Object#wait(long, int) Object.wait}
      * using this time unit.
      * This is a convenience method that converts timeout arguments
-     * into the form required by the <tt>Object.wait</tt> method.
+     * into the form required by the {@code Object.wait} method.
      *
-     * <p>For example, you could implement a blocking <tt>poll</tt>
+     * <p>For example, you could implement a blocking {@code poll}
      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
      * using:
      *
@@ -298,7 +298,7 @@
      * Performs a timed {@link Thread#join(long, int) Thread.join}
      * using this time unit.
      * This is a convenience method that converts time arguments into the
-     * form required by the <tt>Thread.join</tt> method.
+     * form required by the {@code Thread.join} method.
      *
      * @param thread the thread to wait for
      * @param timeout the maximum time to wait. If less than
@@ -318,7 +318,7 @@
      * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
      * this time unit.
      * This is a convenience method that converts time arguments into the
-     * form required by the <tt>Thread.sleep</tt> method.
+     * form required by the {@code Thread.sleep} method.
      *
      * @param timeout the minimum time to sleep. If less than
      * or equal to zero, do not sleep at all.
diff --git a/luni/src/main/java/java/util/concurrent/TimeoutException.java b/luni/src/main/java/java/util/concurrent/TimeoutException.java
index 83934f0..1d7e634 100644
--- a/luni/src/main/java/java/util/concurrent/TimeoutException.java
+++ b/luni/src/main/java/java/util/concurrent/TimeoutException.java
@@ -11,7 +11,7 @@
  * operations for which a timeout is specified need a means to
  * indicate that the timeout has occurred. For many such operations it
  * is possible to return a value that indicates timeout; when that is
- * not possible or desirable then <tt>TimeoutException</tt> should be
+ * not possible or desirable then {@code TimeoutException} should be
  * declared and thrown.
  *
  * @since 1.5
@@ -21,13 +21,13 @@
     private static final long serialVersionUID = 1900926677490660714L;
 
     /**
-     * Constructs a <tt>TimeoutException</tt> with no specified detail
+     * Constructs a {@code TimeoutException} with no specified detail
      * message.
      */
     public TimeoutException() {}
 
     /**
-     * Constructs a <tt>TimeoutException</tt> with the specified detail
+     * Constructs a {@code TimeoutException} with the specified detail
      * message.
      *
      * @param message the detail message
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
index d531f25..13b12aa 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
@@ -76,13 +76,13 @@
      * Atomically sets the value to the given updated value
      * if the current value {@code ==} the expected value.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public boolean weakCompareAndSet(boolean expect, boolean update) {
         int e = expect ? 1 : 0;
@@ -126,7 +126,7 @@
 
     /**
      * Returns the String representation of the current value.
-     * @return the String representation of the current value.
+     * @return the String representation of the current value
      */
     public String toString() {
         return Boolean.toString(get());
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
index e0a0018..d67b20a 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
@@ -110,13 +110,13 @@
      * Atomically sets the value to the given updated value
      * if the current value {@code ==} the expected value.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int expect, int update) {
         return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
@@ -210,13 +210,12 @@
 
     /**
      * Returns the String representation of the current value.
-     * @return the String representation of the current value.
+     * @return the String representation of the current value
      */
     public String toString() {
         return Integer.toString(get());
     }
 
-
     /**
      * Returns the value of this {@code AtomicInteger} as an {@code int}.
      */
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
index 804a51e..1f6980d 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -146,14 +146,14 @@
      * Atomically sets the element at position {@code i} to the given
      * updated value if the current value {@code ==} the expected value.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int i, int expect, int update) {
         return compareAndSet(i, expect, update);
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index c7ed158..6067152 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -8,7 +8,8 @@
 
 import dalvik.system.VMStack; // android-added
 import sun.misc.Unsafe;
-import java.lang.reflect.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -28,7 +29,7 @@
  * @author Doug Lea
  * @param <T> The type of the object holding the updatable field
  */
-public abstract class  AtomicIntegerFieldUpdater<T> {
+public abstract class AtomicIntegerFieldUpdater<T> {
     /**
      * Creates and returns an updater for objects with the given field.
      * The Class argument is needed to check that reflective types and
@@ -40,7 +41,9 @@
      * @throws IllegalArgumentException if the field is not a
      * volatile integer type
      * @throws RuntimeException with a nested reflection-based
-     * exception if the class does not hold field or is the wrong type
+     * exception if the class does not hold field or is the wrong type,
+     * or the field is inaccessible to the caller according to Java language
+     * access control
      */
     public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
         return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
@@ -75,9 +78,9 @@
      * other calls to {@code compareAndSet} and {@code set}, but not
      * necessarily with respect to other changes in the field.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
@@ -108,7 +111,6 @@
      */
     public abstract void lazySet(T obj, int newValue);
 
-
     /**
      * Gets the current value held in the field of the given object managed
      * by this updater.
@@ -242,19 +244,28 @@
         private final Class<?> cclass;
 
         AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) {
-            Field field = null;
-            Class<?> caller = null;
-            int modifiers = 0;
+            final Field field;
+            final Class<?> caller;
+            final int modifiers;
             try {
-                field = tclass.getDeclaredField(fieldName);
+                field = tclass.getDeclaredField(fieldName); // android-changed
                 caller = VMStack.getStackClass2(); // android-changed
-                modifiers = field.getModifiers();
 
+                modifiers = field.getModifiers();
                 // BEGIN android-removed
                 // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
                 //     caller, tclass, null, modifiers);
-                // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                // ClassLoader cl = tclass.getClassLoader();
+                // ClassLoader ccl = caller.getClassLoader();
+                // if ((ccl != null) && (ccl != cl) &&
+                //     ((cl == null) || !isAncestor(cl, ccl))) {
+                //   sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                // }
                 // END android-removed
+            // BEGIN android-removed
+            // } catch (PrivilegedActionException pae) {
+            //     throw new RuntimeException(pae.getException());
+            // END android-removed
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -272,6 +283,23 @@
             offset = unsafe.objectFieldOffset(field);
         }
 
+        // BEGIN android-removed
+        // /**
+        //  * Returns true if the second classloader can be found in the first
+        //  * classloader's delegation chain.
+        //  * Equivalent to the inaccessible: first.isAncestor(second).
+        //  */
+        //  private static boolean isAncestor(ClassLoader first, ClassLoader second) {
+        //     ClassLoader acl = first;
+        //     do {
+        //         acl = acl.getParent();
+        //         if (second == acl) {
+        //             return true;
+        //         }
+        //     } while (acl != null);
+        //     return false;
+        // }
+        // END android-removed
         private void fullCheck(T obj) {
             if (!tclass.isInstance(obj))
                 throw new ClassCastException();
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
index 5e799f7..278c5b5 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
@@ -124,13 +124,13 @@
      * Atomically sets the value to the given updated value
      * if the current value {@code ==} the expected value.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(long expect, long update) {
         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
@@ -224,13 +224,12 @@
 
     /**
      * Returns the String representation of the current value.
-     * @return the String representation of the current value.
+     * @return the String representation of the current value
      */
     public String toString() {
         return Long.toString(get());
     }
 
-
     /**
      * Returns the value of this {@code AtomicLong} as an {@code int}
      * after a narrowing primitive conversion.
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
index 22edb3f..2e8c2b7 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
@@ -106,7 +106,6 @@
         unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);
     }
 
-
     /**
      * Atomically sets the element at position {@code i} to the given value
      * and returns the old value.
@@ -146,14 +145,14 @@
      * Atomically sets the element at position {@code i} to the given
      * updated value if the current value {@code ==} the expected value.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int i, long expect, long update) {
         return compareAndSet(i, expect, update);
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index 748ae69..0096a6b 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -8,7 +8,8 @@
 
 import dalvik.system.VMStack; // android-added
 import sun.misc.Unsafe;
-import java.lang.reflect.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -28,19 +29,21 @@
  * @author Doug Lea
  * @param <T> The type of the object holding the updatable field
  */
-public abstract class  AtomicLongFieldUpdater<T> {
+public abstract class AtomicLongFieldUpdater<T> {
     /**
      * Creates and returns an updater for objects with the given field.
      * The Class argument is needed to check that reflective types and
      * generic types match.
      *
      * @param tclass the class of the objects holding the field
-     * @param fieldName the name of the field to be updated.
+     * @param fieldName the name of the field to be updated
      * @return the updater
      * @throws IllegalArgumentException if the field is not a
-     * volatile long type.
+     * volatile long type
      * @throws RuntimeException with a nested reflection-based
-     * exception if the class does not hold field or is the wrong type.
+     * exception if the class does not hold field or is the wrong type,
+     * or the field is inaccessible to the caller according to Java language
+     * access control
      */
     public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
         if (AtomicLong.VM_SUPPORTS_LONG_CAS)
@@ -65,9 +68,9 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      * @throws ClassCastException if {@code obj} is not an instance
-     * of the class possessing the field established in the constructor.
+     * of the class possessing the field established in the constructor
      */
     public abstract boolean compareAndSet(T obj, long expect, long update);
 
@@ -78,16 +81,16 @@
      * other calls to {@code compareAndSet} and {@code set}, but not
      * necessarily with respect to other changes in the field.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      * @throws ClassCastException if {@code obj} is not an instance
-     * of the class possessing the field established in the constructor.
+     * of the class possessing the field established in the constructor
      */
     public abstract boolean weakCompareAndSet(T obj, long expect, long update);
 
@@ -241,18 +244,27 @@
         private final Class<?> cclass;
 
         CASUpdater(Class<T> tclass, String fieldName) {
-            Field field = null;
-            Class<?> caller = null;
-            int modifiers = 0;
+            final Field field;
+            final Class<?> caller;
+            final int modifiers;
             try {
-                field = tclass.getDeclaredField(fieldName);
+                field = tclass.getDeclaredField(fieldName); // android-changed
                 caller = VMStack.getStackClass2(); // android-changed
                 modifiers = field.getModifiers();
                 // BEGIN android-removed
                 // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
                 //     caller, tclass, null, modifiers);
-                // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                // ClassLoader cl = tclass.getClassLoader();
+                // ClassLoader ccl = caller.getClassLoader();
+                // if ((ccl != null) && (ccl != cl) &&
+                //     ((cl == null) || !isAncestor(cl, ccl))) {
+                //   sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                // }
                 // END android-removed
+            // BEGIN android-removed
+            // } catch (PrivilegedActionException pae) {
+            //    throw new RuntimeException(pae.getException());
+            // END android-removed
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -330,14 +342,23 @@
             Class<?> caller = null;
             int modifiers = 0;
             try {
-                field = tclass.getDeclaredField(fieldName);
+                field = tclass.getDeclaredField(fieldName); // android-changed
                 caller = VMStack.getStackClass2(); // android-changed
                 modifiers = field.getModifiers();
                 // BEGIN android-removed
                 // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
                 //     caller, tclass, null, modifiers);
-                // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                // ClassLoader cl = tclass.getClassLoader();
+                // ClassLoader ccl = caller.getClassLoader();
+                // if ((ccl != null) && (ccl != cl) &&
+                //     ((cl == null) || !isAncestor(cl, ccl))) {
+                //   sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+                // }
                 // END android-removed
+            // BEGIN android-removed
+            // } catch (PrivilegedActionException pae) {
+            //     throw new RuntimeException(pae.getException());
+            // END android-removed
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -410,4 +431,22 @@
             );
         }
     }
+
+    // BEGIN android-removed
+    // /**
+    //  * Returns true if the second classloader can be found in the first
+    //  * classloader's delegation chain.
+    //  * Equivalent to the inaccessible: first.isAncestor(second).
+    //  */
+    // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
+    //     ClassLoader acl = first;
+    //     do {
+    //         acl = acl.getParent();
+    //         if (second == acl) {
+    //             return true;
+    //        }
+    //     } while (acl != null);
+    //     return false;
+    // }
+    // END android-removed
 }
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
index eaf700c..1257be0 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
@@ -83,9 +83,9 @@
      * current reference is {@code ==} to the expected reference
      * and the current mark is equal to the expected mark.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param expectedReference the expected value of the reference
      * @param newReference the new value for the reference
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
index b21e9b6..98b402a 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
@@ -15,7 +15,7 @@
  * @author Doug Lea
  * @param <V> The type of object referred to by this reference
  */
-public class AtomicReference<V>  implements java.io.Serializable {
+public class AtomicReference<V> implements java.io.Serializable {
     private static final long serialVersionUID = -1848883965231344442L;
 
     private static final Unsafe unsafe = Unsafe.getUnsafe();
@@ -89,13 +89,13 @@
      * Atomically sets the value to the given updated value
      * if the current value {@code ==} the expected value.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(V expect, V update) {
         return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
@@ -117,7 +117,7 @@
 
     /**
      * Returns the String representation of the current value.
-     * @return the String representation of the current value.
+     * @return the String representation of the current value
      */
     public String toString() {
         return String.valueOf(get());
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
index c47728d..052b839 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
@@ -29,19 +29,18 @@
     private final Object[] array; // must have exact type Object[]
 
     static {
-        int scale;
         try {
             unsafe = Unsafe.getUnsafe();
             arrayFieldOffset = unsafe.objectFieldOffset
                 (AtomicReferenceArray.class.getDeclaredField("array"));
             base = unsafe.arrayBaseOffset(Object[].class);
-            scale = unsafe.arrayIndexScale(Object[].class);
+            int scale = unsafe.arrayIndexScale(Object[].class);
+            if ((scale & (scale - 1)) != 0)
+                throw new Error("data type scale not a power of two");
+            shift = 31 - Integer.numberOfLeadingZeros(scale);
         } catch (Exception e) {
             throw new Error(e);
         }
-        if ((scale & (scale - 1)) != 0)
-            throw new Error("data type scale not a power of two");
-        shift = 31 - Integer.numberOfLeadingZeros(scale);
     }
 
     private long checkedByteOffset(int i) {
@@ -96,6 +95,7 @@
         return getRaw(checkedByteOffset(i));
     }
 
+    @SuppressWarnings("unchecked")
     private E getRaw(long offset) {
         return (E) unsafe.getObjectVolatile(array, offset);
     }
@@ -121,7 +121,6 @@
         unsafe.putOrderedObject(array, checkedByteOffset(i), newValue);
     }
 
-
     /**
      * Atomically sets the element at position {@code i} to the given
      * value and returns the old value.
@@ -161,14 +160,14 @@
      * Atomically sets the element at position {@code i} to the given
      * updated value if the current value {@code ==} the expected value.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param i the index
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public final boolean weakCompareAndSet(int i, E expect, E update) {
         return compareAndSet(i, expect, update);
@@ -195,7 +194,6 @@
 
     /**
      * Reconstitutes the instance from a stream (that is, deserializes it).
-     * @param s the stream
      */
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException,
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index d23d766..eb2d73e 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -7,7 +7,8 @@
 package java.util.concurrent.atomic;
 import dalvik.system.VMStack; // android-added
 import sun.misc.Unsafe;
-import java.lang.reflect.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 
 /**
  * A reflection-based utility that enables atomic updates to
@@ -45,20 +46,22 @@
  * @param <T> The type of the object holding the updatable field
  * @param <V> The type of the field
  */
-public abstract class AtomicReferenceFieldUpdater<T, V> {
+public abstract class AtomicReferenceFieldUpdater<T,V> {
 
     /**
      * Creates and returns an updater for objects with the given field.
      * The Class arguments are needed to check that reflective types and
      * generic types match.
      *
-     * @param tclass the class of the objects holding the field.
+     * @param tclass the class of the objects holding the field
      * @param vclass the class of the field
-     * @param fieldName the name of the field to be updated.
+     * @param fieldName the name of the field to be updated
      * @return the updater
-     * @throws IllegalArgumentException if the field is not a volatile reference type.
+     * @throws IllegalArgumentException if the field is not a volatile reference type
      * @throws RuntimeException with a nested reflection-based
-     * exception if the class does not hold field or is the wrong type.
+     * exception if the class does not hold field or is the wrong type,
+     * or the field is inaccessible to the caller according to Java language
+     * access control
      */
     public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
         return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
@@ -82,7 +85,7 @@
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public abstract boolean compareAndSet(T obj, V expect, V update);
 
@@ -93,14 +96,14 @@
      * other calls to {@code compareAndSet} and {@code set}, but not
      * necessarily with respect to other changes in the field.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
+     * @return true if successful
      */
     public abstract boolean weakCompareAndSet(T obj, V expect, V update);
 
@@ -169,23 +172,32 @@
          * screenings fail.
          */
 
-        AtomicReferenceFieldUpdaterImpl(Class<T> tclass,
+        AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
                                         Class<V> vclass,
-                                        String fieldName) {
-            Field field = null;
-            Class<?> fieldClass = null;
-            Class<?> caller = null;
-            int modifiers = 0;
+                                        final String fieldName) {
+            final Field field;
+            final Class<?> fieldClass;
+            final Class<?> caller;
+            final int modifiers;
             try {
-                field = tclass.getDeclaredField(fieldName);
+                field = tclass.getDeclaredField(fieldName); // android-changed
                 caller = VMStack.getStackClass2(); // android-changed
                 modifiers = field.getModifiers();
-                // BEGIN android-removed
-                // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
-                //     caller, tclass, null, modifiers);
-                // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
-                // END android-removed
+            // BEGIN android-removed
+            //     sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+            //         caller, tclass, null, modifiers);
+            //     ClassLoader cl = tclass.getClassLoader();
+            //     ClassLoader ccl = caller.getClassLoader();
+            //     if ((ccl != null) && (ccl != cl) &&
+            //         ((cl == null) || !isAncestor(cl, ccl))) {
+            //       sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+            //     }
+            // END android-removed
                 fieldClass = field.getType();
+            // BEGIN android-removed
+            // } catch (PrivilegedActionException pae) {
+            //     throw new RuntimeException(pae.getException());
+            // END android-removed
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -206,6 +218,25 @@
             offset = unsafe.objectFieldOffset(field);
         }
 
+        // BEGIN android-removed
+        // /**
+        //  * Returns true if the second classloader can be found in the first
+        //  * classloader's delegation chain.
+        //  * Equivalent to the inaccessible: first.isAncestor(second).
+        //  */
+        //
+        // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
+        //     ClassLoader acl = first;
+        //     do {
+        //         acl = acl.getParent();
+        //         if (second == acl) {
+        //             return true;
+        //        }
+        //     } while (acl != null);
+        //     return false;
+        // }
+        // END android-removed
+
         void targetCheck(T obj) {
             if (!tclass.isInstance(obj))
                 throw new ClassCastException();
@@ -254,6 +285,7 @@
             unsafe.putOrderedObject(obj, offset, newValue);
         }
 
+        @SuppressWarnings("unchecked")
         public V get(T obj) {
             if (obj == null || obj.getClass() != tclass || cclass != null)
                 targetCheck(obj);
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
index a0cb492..b93a6f3 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
@@ -83,9 +83,9 @@
      * current reference is {@code ==} to the expected reference
      * and the current stamp is equal to the expected stamp.
      *
-     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
-     * and does not provide ordering guarantees, so is only rarely an
-     * appropriate alternative to {@code compareAndSet}.
+     * <p><a href="package-summary.html#weakCompareAndSet">May fail
+     * spuriously and does not provide ordering guarantees</a>, so is
+     * only rarely an appropriate alternative to {@code compareAndSet}.
      *
      * @param expectedReference the expected value of the reference
      * @param newReference the new value for the reference
@@ -126,7 +126,6 @@
              casPair(current, Pair.of(newReference, newStamp)));
     }
 
-
     /**
      * Unconditionally sets the value of both the reference and stamp.
      *
diff --git a/luni/src/main/java/java/util/concurrent/atomic/package-info.java b/luni/src/main/java/java/util/concurrent/atomic/package-info.java
index efbb413..568d2c6 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/package-info.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/package-info.java
@@ -54,19 +54,20 @@
  *
  * write your utility method as follows:
  *  <pre> {@code
- * boolean getAndTransform(AtomicLong var) {
+ * long getAndTransform(AtomicLong var) {
  *   while (true) {
  *     long current = var.get();
  *     long next = transform(current);
  *     if (var.compareAndSet(current, next))
  *         return current;
+ *         // return next; for transformAndGet
  *   }
  * }}</pre>
  *
  * <p>The memory effects for accesses and updates of atomics generally
  * follow the rules for volatiles, as stated in
- * <a href="http://java.sun.com/docs/books/jls/"> The Java Language
- * Specification, Third Edition (17.4 Memory Model)</a>:
+ * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4">
+ * The Java Language Specification (17.4 Memory Model)</a>:
  *
  * <ul>
  *
@@ -122,13 +123,12 @@
  * semantics for their array elements, which is not supported for
  * ordinary arrays.
  *
- * <a name="Spurious">
- * <p>The atomic classes also support method {@code weakCompareAndSet},
- * which has limited applicability.  On some platforms, the weak version
- * may be more efficient than {@code compareAndSet} in the normal case,
- * but differs in that any given invocation of the
- * {@code weakCompareAndSet} method may return {@code false}
- * <em>spuriously</em> (that is, for no apparent reason)</a>.  A
+ * <p id="weakCompareAndSet">The atomic classes also support method
+ * {@code weakCompareAndSet}, which has limited applicability.  On some
+ * platforms, the weak version may be more efficient than {@code
+ * compareAndSet} in the normal case, but differs in that any given
+ * invocation of the {@code weakCompareAndSet} method may return {@code
+ * false} <em>spuriously</em> (that is, for no apparent reason).  A
  * {@code false} return means only that the operation may be retried if
  * desired, relying on the guarantee that repeated invocation when the
  * variable holds {@code expectedValue} and no other thread is also
@@ -164,7 +164,7 @@
  *
  * <p>Atomic classes are not general purpose replacements for
  * {@code java.lang.Integer} and related classes.  They do <em>not</em>
- * define methods such as {@code hashCode} and
+ * define methods such as {@code equals}, {@code hashCode} and
  * {@code compareTo}.  (Because atomic variables are expected to be
  * mutated, they are poor choices for hash table keys.)  Additionally,
  * classes are provided only for those types that are commonly useful in
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
index 4bec0cf..fa01824 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
@@ -10,7 +10,7 @@
  * A synchronizer that may be exclusively owned by a thread.  This
  * class provides a basis for creating locks and related synchronizers
  * that may entail a notion of ownership.  The
- * <tt>AbstractOwnableSynchronizer</tt> class itself does not manage or
+ * {@code AbstractOwnableSynchronizer} class itself does not manage or
  * use this information. However, subclasses and tools may use
  * appropriately maintained values to help control and monitor access
  * and provide diagnostics.
@@ -36,9 +36,9 @@
 
     /**
      * Sets the thread that currently owns exclusive access. A
-     * <tt>null</tt> argument indicates that no thread owns access.
+     * {@code null} argument indicates that no thread owns access.
      * This method does not otherwise impose any synchronization or
-     * <tt>volatile</tt> field accesses.
+     * {@code volatile} field accesses.
      */
     protected final void setExclusiveOwnerThread(Thread t) {
         exclusiveOwnerThread = t;
@@ -46,9 +46,9 @@
 
     /**
      * Returns the thread last set by
-     * <tt>setExclusiveOwnerThread</tt>, or <tt>null</tt> if never
+     * {@code setExclusiveOwnerThread}, or {@code null} if never
      * set.  This method does not otherwise impose any synchronization
-     * or <tt>volatile</tt> field accesses.
+     * or {@code volatile} field accesses.
      * @return the owner thread
      */
     protected final Thread getExclusiveOwnerThread() {
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
index 7b36460..4c5e280 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
@@ -5,17 +5,19 @@
  */
 
 package java.util.concurrent.locks;
-import java.util.*;
-import java.util.concurrent.*;
+import java.util.concurrent.TimeUnit;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
 import sun.misc.Unsafe;
 
 /**
  * A version of {@link AbstractQueuedSynchronizer} in
- * which synchronization state is maintained as a <tt>long</tt>.
+ * which synchronization state is maintained as a {@code long}.
  * This class has exactly the same structure, properties, and methods
- * as <tt>AbstractQueuedSynchronizer</tt> with the exception
+ * as {@code AbstractQueuedSynchronizer} with the exception
  * that all state-related parameters and results are defined
- * as <tt>long</tt> rather than <tt>int</tt>. This class
+ * as {@code long} rather than {@code int}. This class
  * may be useful when creating synchronizers such as
  * multilevel locks and barriers that require
  * 64 bits of state.
@@ -40,7 +42,7 @@
     */
 
     /**
-     * Creates a new <tt>AbstractQueuedLongSynchronizer</tt> instance
+     * Creates a new {@code AbstractQueuedLongSynchronizer} instance
      * with initial synchronization state of zero.
      */
     protected AbstractQueuedLongSynchronizer() { }
@@ -73,7 +75,7 @@
      *
      * <p>Insertion into a CLH queue requires only a single atomic
      * operation on "tail", so there is a simple atomic point of
-     * demarcation from unqueued to queued. Similarly, dequeing
+     * demarcation from unqueued to queued. Similarly, dequeuing
      * involves only updating the "head". However, it takes a bit
      * more work for nodes to determine who their successors are,
      * in part to deal with possible cancellation due to timeouts
@@ -180,7 +182,7 @@
 
         /**
          * Link to predecessor node that current node/thread relies on
-         * for checking waitStatus. Assigned during enqueing, and nulled
+         * for checking waitStatus. Assigned during enqueuing, and nulled
          * out (for sake of GC) only upon dequeuing.  Also, upon
          * cancellation of a predecessor, we short-circuit while
          * finding a non-cancelled one, which will always exist
@@ -225,7 +227,7 @@
         Node nextWaiter;
 
         /**
-         * Returns true if node is waiting in shared mode
+         * @return true if node is waiting in shared mode
          */
         final boolean isShared() {
             return nextWaiter == SHARED;
@@ -281,7 +283,7 @@
 
     /**
      * Returns the current value of synchronization state.
-     * This operation has memory semantics of a <tt>volatile</tt> read.
+     * This operation has memory semantics of a {@code volatile} read.
      * @return current state value
      */
     protected final long getState() {
@@ -290,7 +292,7 @@
 
     /**
      * Sets the value of synchronization state.
-     * This operation has memory semantics of a <tt>volatile</tt> write.
+     * This operation has memory semantics of a {@code volatile} write.
      * @param newState the new state value
      */
     protected final void setState(long newState) {
@@ -300,7 +302,7 @@
     /**
      * Atomically sets synchronization state to the given updated
      * value if the current state value equals the expected value.
-     * This operation has memory semantics of a <tt>volatile</tt> read
+     * This operation has memory semantics of a {@code volatile} read
      * and write.
      *
      * @param expect the expected value
@@ -410,7 +412,7 @@
     }
 
     /**
-     * Release action for shared mode -- signal successor and ensure
+     * Release action for shared mode -- signals successor and ensures
      * propagation. (Note: For exclusive mode, release just amounts
      * to calling unparkSuccessor of head if it needs signal.)
      */
@@ -531,7 +533,7 @@
     /**
      * Checks and updates status for a node that failed to acquire.
      * Returns true if thread should block. This is the main signal
-     * control in all acquire loops.  Requires that pred == node.prev
+     * control in all acquire loops.  Requires that pred == node.prev.
      *
      * @param pred node's predecessor holding status
      * @param node the node
@@ -656,8 +658,10 @@
      * @return {@code true} if acquired
      */
     private boolean doAcquireNanos(long arg, long nanosTimeout)
-        throws InterruptedException {
-        long lastTime = System.nanoTime();
+            throws InterruptedException {
+        if (nanosTimeout <= 0L)
+            return false;
+        final long deadline = System.nanoTime() + nanosTimeout;
         final Node node = addWaiter(Node.EXCLUSIVE);
         boolean failed = true;
         try {
@@ -669,14 +673,12 @@
                     failed = false;
                     return true;
                 }
-                if (nanosTimeout <= 0)
+                nanosTimeout = deadline - System.nanoTime();
+                if (nanosTimeout <= 0L)
                     return false;
                 if (shouldParkAfterFailedAcquire(p, node) &&
                     nanosTimeout > spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
-                long now = System.nanoTime();
-                nanosTimeout -= now - lastTime;
-                lastTime = now;
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
@@ -756,9 +758,10 @@
      * @return {@code true} if acquired
      */
     private boolean doAcquireSharedNanos(long arg, long nanosTimeout)
-        throws InterruptedException {
-
-        long lastTime = System.nanoTime();
+            throws InterruptedException {
+        if (nanosTimeout <= 0L)
+            return false;
+        final long deadline = System.nanoTime() + nanosTimeout;
         final Node node = addWaiter(Node.SHARED);
         boolean failed = true;
         try {
@@ -773,14 +776,12 @@
                         return true;
                     }
                 }
-                if (nanosTimeout <= 0)
+                nanosTimeout = deadline - System.nanoTime();
+                if (nanosTimeout <= 0L)
                     return false;
                 if (shouldParkAfterFailedAcquire(p, node) &&
                     nanosTimeout > spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
-                long now = System.nanoTime();
-                nanosTimeout -= now - lastTime;
-                lastTime = now;
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
@@ -1036,7 +1037,7 @@
      * thread is queued, possibly repeatedly blocking and unblocking,
      * invoking {@link #tryAcquireShared} until success or the thread
      * is interrupted.
-     * @param arg the acquire argument
+     * @param arg the acquire argument.
      * This value is conveyed to {@link #tryAcquireShared} but is
      * otherwise uninterpreted and can represent anything
      * you like.
@@ -1254,8 +1255,9 @@
      *         current thread, and {@code false} if the current thread
      *         is at the head of the queue or the queue is empty
      * @since 1.7
+     * @hide
      */
-    /*public*/ final boolean hasQueuedPredecessors() { // android-changed
+    public final boolean hasQueuedPredecessors() {
         // The correctness of this depends on head being initialized
         // before tail and on head.next being accurate if the current
         // thread is first in queue.
@@ -1411,7 +1413,7 @@
      * Returns true if successful.
      * @param node the node
      * @return true if successfully transferred (else the node was
-     * cancelled before signal).
+     * cancelled before signal)
      */
     final boolean transferForSignal(Node node) {
         /*
@@ -1434,10 +1436,10 @@
     }
 
     /**
-     * Transfers node, if necessary, to sync queue after a cancelled
-     * wait. Returns true if thread was cancelled before being
-     * signalled.
-     * @param node its node
+     * Transfers node, if necessary, to sync queue after a cancelled wait.
+     * Returns true if thread was cancelled before being signalled.
+     *
+     * @param node the node
      * @return true if cancelled before the node was signalled
      */
     final boolean transferAfterCancelledWait(Node node) {
@@ -1485,25 +1487,23 @@
      * uses this synchronizer as its lock.
      *
      * @param condition the condition
-     * @return <tt>true</tt> if owned
+     * @return {@code true} if owned
      * @throws NullPointerException if the condition is null
      */
     public final boolean owns(ConditionObject condition) {
-        if (condition == null)
-            throw new NullPointerException();
         return condition.isOwnedBy(this);
     }
 
     /**
      * Queries whether any threads are waiting on the given condition
      * associated with this synchronizer. Note that because timeouts
-     * and interrupts may occur at any time, a <tt>true</tt> return
-     * does not guarantee that a future <tt>signal</tt> will awaken
+     * and interrupts may occur at any time, a {@code true} return
+     * does not guarantee that a future {@code signal} will awaken
      * any threads.  This method is designed primarily for use in
      * monitoring of the system state.
      *
      * @param condition the condition
-     * @return <tt>true</tt> if there are any waiting threads
+     * @return {@code true} if there are any waiting threads
      * @throws IllegalMonitorStateException if exclusive synchronization
      *         is not held
      * @throws IllegalArgumentException if the given condition is
@@ -1570,7 +1570,7 @@
      * and Condition users. Exported versions of this class will in
      * general need to be accompanied by documentation describing
      * condition semantics that rely on those of the associated
-     * <tt>AbstractQueuedLongSynchronizer</tt>.
+     * {@code AbstractQueuedLongSynchronizer}.
      *
      * <p>This class is Serializable, but all fields are transient,
      * so deserialized conditions have no waiters.
@@ -1585,7 +1585,7 @@
         private transient Node lastWaiter;
 
         /**
-         * Creates a new <tt>ConditionObject</tt> instance.
+         * Creates a new {@code ConditionObject} instance.
          */
         public ConditionObject() { }
 
@@ -1711,9 +1711,8 @@
          * Implements uninterruptible condition wait.
          * <ol>
          * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with
-         *      saved state as argument, throwing
-         *      IllegalMonitorStateException if it fails.
+         * <li> Invoke {@link #release} with saved state as argument,
+         *      throwing IllegalMonitorStateException if it fails.
          * <li> Block until signalled.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
@@ -1772,9 +1771,8 @@
          * <ol>
          * <li> If current thread is interrupted, throw InterruptedException.
          * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with
-         *      saved state as argument, throwing
-         *      IllegalMonitorStateException if it fails.
+         * <li> Invoke {@link #release} with saved state as argument,
+         *      throwing IllegalMonitorStateException if it fails.
          * <li> Block until signalled or interrupted.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
@@ -1805,9 +1803,8 @@
          * <ol>
          * <li> If current thread is interrupted, throw InterruptedException.
          * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with
-         *      saved state as argument, throwing
-         *      IllegalMonitorStateException if it fails.
+         * <li> Invoke {@link #release} with saved state as argument,
+         *      throwing IllegalMonitorStateException if it fails.
          * <li> Block until signalled, interrupted, or timed out.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
@@ -1820,20 +1817,18 @@
                 throw new InterruptedException();
             Node node = addConditionWaiter();
             long savedState = fullyRelease(node);
-            long lastTime = System.nanoTime();
+            final long deadline = System.nanoTime() + nanosTimeout;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
                 if (nanosTimeout <= 0L) {
                     transferAfterCancelledWait(node);
                     break;
                 }
-                LockSupport.parkNanos(this, nanosTimeout);
+                if (nanosTimeout >= spinForTimeoutThreshold)
+                    LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
-
-                long now = System.nanoTime();
-                nanosTimeout -= now - lastTime;
-                lastTime = now;
+                nanosTimeout = deadline - System.nanoTime();
             }
             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                 interruptMode = REINTERRUPT;
@@ -1841,7 +1836,7 @@
                 unlinkCancelledWaiters();
             if (interruptMode != 0)
                 reportInterruptAfterWait(interruptMode);
-            return nanosTimeout - (System.nanoTime() - lastTime);
+            return deadline - System.nanoTime();
         }
 
         /**
@@ -1849,9 +1844,8 @@
          * <ol>
          * <li> If current thread is interrupted, throw InterruptedException.
          * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with
-         *      saved state as argument, throwing
-         *      IllegalMonitorStateException if it fails.
+         * <li> Invoke {@link #release} with saved state as argument,
+         *      throwing IllegalMonitorStateException if it fails.
          * <li> Block until signalled, interrupted, or timed out.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
@@ -1861,8 +1855,6 @@
          */
         public final boolean awaitUntil(Date deadline)
                 throws InterruptedException {
-            if (deadline == null)
-                throw new NullPointerException();
             long abstime = deadline.getTime();
             if (Thread.interrupted())
                 throw new InterruptedException();
@@ -1893,9 +1885,8 @@
          * <ol>
          * <li> If current thread is interrupted, throw InterruptedException.
          * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with
-         *      saved state as argument, throwing
-         *      IllegalMonitorStateException if it fails.
+         * <li> Invoke {@link #release} with saved state as argument,
+         *      throwing IllegalMonitorStateException if it fails.
          * <li> Block until signalled, interrupted, or timed out.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
@@ -1905,14 +1896,12 @@
          */
         public final boolean await(long time, TimeUnit unit)
                 throws InterruptedException {
-            if (unit == null)
-                throw new NullPointerException();
             long nanosTimeout = unit.toNanos(time);
             if (Thread.interrupted())
                 throw new InterruptedException();
             Node node = addConditionWaiter();
             long savedState = fullyRelease(node);
-            long lastTime = System.nanoTime();
+            final long deadline = System.nanoTime() + nanosTimeout;
             boolean timedout = false;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
@@ -1924,9 +1913,7 @@
                     LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
-                long now = System.nanoTime();
-                nanosTimeout -= now - lastTime;
-                lastTime = now;
+                nanosTimeout = deadline - System.nanoTime();
             }
             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                 interruptMode = REINTERRUPT;
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
index 42029f0..0350060 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -5,8 +5,10 @@
  */
 
 package java.util.concurrent.locks;
-import java.util.*;
-import java.util.concurrent.*;
+import java.util.concurrent.TimeUnit;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
 import sun.misc.Unsafe;
 
 // BEGIN android-note
@@ -18,12 +20,12 @@
  * synchronizers (semaphores, events, etc) that rely on
  * first-in-first-out (FIFO) wait queues.  This class is designed to
  * be a useful basis for most kinds of synchronizers that rely on a
- * single atomic <tt>int</tt> value to represent state. Subclasses
+ * single atomic {@code int} value to represent state. Subclasses
  * must define the protected methods that change this state, and which
  * define what that state means in terms of this object being acquired
  * or released.  Given these, the other methods in this class carry
  * out all queuing and blocking mechanics. Subclasses can maintain
- * other state fields, but only the atomically updated <tt>int</tt>
+ * other state fields, but only the atomically updated {@code int}
  * value manipulated using methods {@link #getState}, {@link
  * #setState} and {@link #compareAndSetState} is tracked with respect
  * to synchronization.
@@ -31,7 +33,7 @@
  * <p>Subclasses should be defined as non-public internal helper
  * classes that are used to implement the synchronization properties
  * of their enclosing class.  Class
- * <tt>AbstractQueuedSynchronizer</tt> does not implement any
+ * {@code AbstractQueuedSynchronizer} does not implement any
  * synchronization interface.  Instead it defines methods such as
  * {@link #acquireInterruptibly} that can be invoked as
  * appropriate by concrete locks and related synchronizers to
@@ -58,7 +60,7 @@
  * invoked with the current {@link #getState} value fully releases
  * this object, and {@link #acquire}, given this saved state value,
  * eventually restores this object to its previous acquired state.  No
- * <tt>AbstractQueuedSynchronizer</tt> method otherwise creates such a
+ * {@code AbstractQueuedSynchronizer} method otherwise creates such a
  * condition, so if this constraint cannot be met, do not use it.  The
  * behavior of {@link ConditionObject} depends of course on the
  * semantics of its synchronizer implementation.
@@ -66,13 +68,13 @@
  * <p>This class provides inspection, instrumentation, and monitoring
  * methods for the internal queue, as well as similar methods for
  * condition objects. These can be exported as desired into classes
- * using an <tt>AbstractQueuedSynchronizer</tt> for their
+ * using an {@code AbstractQueuedSynchronizer} for their
  * synchronization mechanics.
  *
  * <p>Serialization of this class stores only the underlying atomic
  * integer maintaining state, so deserialized objects have empty
  * thread queues. Typical subclasses requiring serializability will
- * define a <tt>readObject</tt> method that restores this to a known
+ * define a {@code readObject} method that restores this to a known
  * initial state upon deserialization.
  *
  * <h3>Usage</h3>
@@ -88,14 +90,14 @@
  * <li> {@link #tryAcquireShared}
  * <li> {@link #tryReleaseShared}
  * <li> {@link #isHeldExclusively}
- *</ul>
+ * </ul>
  *
  * Each of these methods by default throws {@link
  * UnsupportedOperationException}.  Implementations of these methods
  * must be internally thread-safe, and should in general be short and
  * not block. Defining these methods is the <em>only</em> supported
  * means of using this class. All other methods are declared
- * <tt>final</tt> because they cannot be independently varied.
+ * {@code final} because they cannot be independently varied.
  *
  * <p>You may also find the inherited methods from {@link
  * AbstractOwnableSynchronizer} useful to keep track of the thread
@@ -121,19 +123,19 @@
  *
  * (Shared mode is similar but may involve cascading signals.)
  *
- * <p><a name="barging">Because checks in acquire are invoked before
+ * <p id="barging">Because checks in acquire are invoked before
  * enqueuing, a newly acquiring thread may <em>barge</em> ahead of
- * others that are blocked and queued. However, you can, if desired,
- * define <tt>tryAcquire</tt> and/or <tt>tryAcquireShared</tt> to
+ * others that are blocked and queued.  However, you can, if desired,
+ * define {@code tryAcquire} and/or {@code tryAcquireShared} to
  * disable barging by internally invoking one or more of the inspection
  * methods. In particular, a strict FIFO lock can define
- * <tt>tryAcquire</tt> to immediately return <tt>false</tt> if {@link
+ * {@code tryAcquire} to immediately return {@code false} if {@link
  * #getFirstQueuedThread} does not return the current thread.  A
  * normally preferable non-strict fair version can immediately return
- * <tt>false</tt> only if {@link #hasQueuedThreads} returns
- * <tt>true</tt> and <tt>getFirstQueuedThread</tt> is not the current
- * thread; or equivalently, that <tt>getFirstQueuedThread</tt> is both
- * non-null and not the current thread.  Further variations are
+ * {@code false} only if {@link #hasQueuedThreads} returns
+ * {@code true} and {@code getFirstQueuedThread} is not the current
+ * thread; or equivalently, that {@code getFirstQueuedThread} is both
+ * non-null and not the current thread. Further variations are
  * possible.
  *
  * <p>Throughput and scalability are generally highest for the
@@ -144,7 +146,7 @@
  * threads, and each recontention has an unbiased chance to succeed
  * against incoming threads.  Also, while acquires do not
  * &quot;spin&quot; in the usual sense, they may perform multiple
- * invocations of <tt>tryAcquire</tt> interspersed with other
+ * invocations of {@code tryAcquire} interspersed with other
  * computations before blocking.  This gives most of the benefits of
  * spins when exclusive synchronization is only briefly held, without
  * most of the liabilities when it isn't. If so desired, you can
@@ -155,7 +157,7 @@
  *
  * <p>This class provides an efficient and scalable basis for
  * synchronization in part by specializing its range of use to
- * synchronizers that can rely on <tt>int</tt> state, acquire, and
+ * synchronizers that can rely on {@code int} state, acquire, and
  * release parameters, and an internal FIFO wait queue. When this does
  * not suffice, you can build synchronizers from a lower level using
  * {@link java.util.concurrent.atomic atomic} classes, your own custom
@@ -177,12 +179,12 @@
  *
  *   // Our internal helper class
  *   private static class Sync extends AbstractQueuedSynchronizer {
- *     // Report whether in locked state
+ *     // Reports whether in locked state
  *     protected boolean isHeldExclusively() {
  *       return getState() == 1;
  *     }
  *
- *     // Acquire the lock if state is zero
+ *     // Acquires the lock if state is zero
  *     public boolean tryAcquire(int acquires) {
  *       assert acquires == 1; // Otherwise unused
  *       if (compareAndSetState(0, 1)) {
@@ -192,7 +194,7 @@
  *       return false;
  *     }
  *
- *     // Release the lock by setting state to zero
+ *     // Releases the lock by setting state to zero
  *     protected boolean tryRelease(int releases) {
  *       assert releases == 1; // Otherwise unused
  *       if (getState() == 0) throw new IllegalMonitorStateException();
@@ -201,10 +203,10 @@
  *       return true;
  *     }
  *
- *     // Provide a Condition
+ *     // Provides a Condition
  *     Condition newCondition() { return new ConditionObject(); }
  *
- *     // Deserialize properly
+ *     // Deserializes properly
  *     private void readObject(ObjectInputStream s)
  *         throws IOException, ClassNotFoundException {
  *       s.defaultReadObject();
@@ -230,9 +232,10 @@
  *   }
  * }}</pre>
  *
- * <p>Here is a latch class that is like a {@link CountDownLatch}
- * except that it only requires a single <tt>signal</tt> to
- * fire. Because a latch is non-exclusive, it uses the <tt>shared</tt>
+ * <p>Here is a latch class that is like a
+ * {@link java.util.concurrent.CountDownLatch CountDownLatch}
+ * except that it only requires a single {@code signal} to
+ * fire. Because a latch is non-exclusive, it uses the {@code shared}
  * acquire and release methods.
  *
  *  <pre> {@code
@@ -269,7 +272,7 @@
     private static final long serialVersionUID = 7373984972572414691L;
 
     /**
-     * Creates a new <tt>AbstractQueuedSynchronizer</tt> instance
+     * Creates a new {@code AbstractQueuedSynchronizer} instance
      * with initial synchronization state of zero.
      */
     protected AbstractQueuedSynchronizer() { }
@@ -302,7 +305,7 @@
      *
      * <p>Insertion into a CLH queue requires only a single atomic
      * operation on "tail", so there is a simple atomic point of
-     * demarcation from unqueued to queued. Similarly, dequeing
+     * demarcation from unqueued to queued. Similarly, dequeuing
      * involves only updating the "head". However, it takes a bit
      * more work for nodes to determine who their successors are,
      * in part to deal with possible cancellation due to timeouts
@@ -409,7 +412,7 @@
 
         /**
          * Link to predecessor node that current node/thread relies on
-         * for checking waitStatus. Assigned during enqueing, and nulled
+         * for checking waitStatus. Assigned during enqueuing, and nulled
          * out (for sake of GC) only upon dequeuing.  Also, upon
          * cancellation of a predecessor, we short-circuit while
          * finding a non-cancelled one, which will always exist
@@ -454,7 +457,7 @@
         Node nextWaiter;
 
         /**
-         * Returns true if node is waiting in shared mode
+         * Returns true if node is waiting in shared mode.
          */
         final boolean isShared() {
             return nextWaiter == SHARED;
@@ -510,7 +513,7 @@
 
     /**
      * Returns the current value of synchronization state.
-     * This operation has memory semantics of a <tt>volatile</tt> read.
+     * This operation has memory semantics of a {@code volatile} read.
      * @return current state value
      */
     protected final int getState() {
@@ -519,7 +522,7 @@
 
     /**
      * Sets the value of synchronization state.
-     * This operation has memory semantics of a <tt>volatile</tt> write.
+     * This operation has memory semantics of a {@code volatile} write.
      * @param newState the new state value
      */
     protected final void setState(int newState) {
@@ -529,7 +532,7 @@
     /**
      * Atomically sets synchronization state to the given updated
      * value if the current state value equals the expected value.
-     * This operation has memory semantics of a <tt>volatile</tt> read
+     * This operation has memory semantics of a {@code volatile} read
      * and write.
      *
      * @param expect the expected value
@@ -639,7 +642,7 @@
     }
 
     /**
-     * Release action for shared mode -- signal successor and ensure
+     * Release action for shared mode -- signals successor and ensures
      * propagation. (Note: For exclusive mode, release just amounts
      * to calling unparkSuccessor of head if it needs signal.)
      */
@@ -760,7 +763,7 @@
     /**
      * Checks and updates status for a node that failed to acquire.
      * Returns true if thread should block. This is the main signal
-     * control in all acquire loops.  Requires that pred == node.prev
+     * control in all acquire loops.  Requires that pred == node.prev.
      *
      * @param pred node's predecessor holding status
      * @param node the node
@@ -885,8 +888,10 @@
      * @return {@code true} if acquired
      */
     private boolean doAcquireNanos(int arg, long nanosTimeout)
-        throws InterruptedException {
-        long lastTime = System.nanoTime();
+            throws InterruptedException {
+        if (nanosTimeout <= 0L)
+            return false;
+        final long deadline = System.nanoTime() + nanosTimeout;
         final Node node = addWaiter(Node.EXCLUSIVE);
         boolean failed = true;
         try {
@@ -898,14 +903,12 @@
                     failed = false;
                     return true;
                 }
-                if (nanosTimeout <= 0)
+                nanosTimeout = deadline - System.nanoTime();
+                if (nanosTimeout <= 0L)
                     return false;
                 if (shouldParkAfterFailedAcquire(p, node) &&
                     nanosTimeout > spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
-                long now = System.nanoTime();
-                nanosTimeout -= now - lastTime;
-                lastTime = now;
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
@@ -985,9 +988,10 @@
      * @return {@code true} if acquired
      */
     private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
-        throws InterruptedException {
-
-        long lastTime = System.nanoTime();
+            throws InterruptedException {
+        if (nanosTimeout <= 0L)
+            return false;
+        final long deadline = System.nanoTime() + nanosTimeout;
         final Node node = addWaiter(Node.SHARED);
         boolean failed = true;
         try {
@@ -1002,14 +1006,12 @@
                         return true;
                     }
                 }
-                if (nanosTimeout <= 0)
+                nanosTimeout = deadline - System.nanoTime();
+                if (nanosTimeout <= 0L)
                     return false;
                 if (shouldParkAfterFailedAcquire(p, node) &&
                     nanosTimeout > spinForTimeoutThreshold)
                     LockSupport.parkNanos(this, nanosTimeout);
-                long now = System.nanoTime();
-                nanosTimeout -= now - lastTime;
-                lastTime = now;
                 if (Thread.interrupted())
                     throw new InterruptedException();
             }
@@ -1265,7 +1267,7 @@
      * thread is queued, possibly repeatedly blocking and unblocking,
      * invoking {@link #tryAcquireShared} until success or the thread
      * is interrupted.
-     * @param arg the acquire argument
+     * @param arg the acquire argument.
      * This value is conveyed to {@link #tryAcquireShared} but is
      * otherwise uninterpreted and can represent anything
      * you like.
@@ -1641,7 +1643,7 @@
      * Returns true if successful.
      * @param node the node
      * @return true if successfully transferred (else the node was
-     * cancelled before signal).
+     * cancelled before signal)
      */
     final boolean transferForSignal(Node node) {
         /*
@@ -1664,10 +1666,10 @@
     }
 
     /**
-     * Transfers node, if necessary, to sync queue after a cancelled
-     * wait. Returns true if thread was cancelled before being
-     * signalled.
-     * @param node its node
+     * Transfers node, if necessary, to sync queue after a cancelled wait.
+     * Returns true if thread was cancelled before being signalled.
+     *
+     * @param node the node
      * @return true if cancelled before the node was signalled
      */
     final boolean transferAfterCancelledWait(Node node) {
@@ -1715,25 +1717,23 @@
      * uses this synchronizer as its lock.
      *
      * @param condition the condition
-     * @return <tt>true</tt> if owned
+     * @return {@code true} if owned
      * @throws NullPointerException if the condition is null
      */
     public final boolean owns(ConditionObject condition) {
-        if (condition == null)
-            throw new NullPointerException();
         return condition.isOwnedBy(this);
     }
 
     /**
      * Queries whether any threads are waiting on the given condition
      * associated with this synchronizer. Note that because timeouts
-     * and interrupts may occur at any time, a <tt>true</tt> return
-     * does not guarantee that a future <tt>signal</tt> will awaken
+     * and interrupts may occur at any time, a {@code true} return
+     * does not guarantee that a future {@code signal} will awaken
      * any threads.  This method is designed primarily for use in
      * monitoring of the system state.
      *
      * @param condition the condition
-     * @return <tt>true</tt> if there are any waiting threads
+     * @return {@code true} if there are any waiting threads
      * @throws IllegalMonitorStateException if exclusive synchronization
      *         is not held
      * @throws IllegalArgumentException if the given condition is
@@ -1800,7 +1800,7 @@
      * and Condition users. Exported versions of this class will in
      * general need to be accompanied by documentation describing
      * condition semantics that rely on those of the associated
-     * <tt>AbstractQueuedSynchronizer</tt>.
+     * {@code AbstractQueuedSynchronizer}.
      *
      * <p>This class is Serializable, but all fields are transient,
      * so deserialized conditions have no waiters.
@@ -1813,7 +1813,7 @@
         private transient Node lastWaiter;
 
         /**
-         * Creates a new <tt>ConditionObject</tt> instance.
+         * Creates a new {@code ConditionObject} instance.
          */
         public ConditionObject() { }
 
@@ -1939,9 +1939,8 @@
          * Implements uninterruptible condition wait.
          * <ol>
          * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with
-         *      saved state as argument, throwing
-         *      IllegalMonitorStateException if it fails.
+         * <li> Invoke {@link #release} with saved state as argument,
+         *      throwing IllegalMonitorStateException if it fails.
          * <li> Block until signalled.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
@@ -2000,9 +1999,8 @@
          * <ol>
          * <li> If current thread is interrupted, throw InterruptedException.
          * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with
-         *      saved state as argument, throwing
-         *      IllegalMonitorStateException if it fails.
+         * <li> Invoke {@link #release} with saved state as argument,
+         *      throwing IllegalMonitorStateException if it fails.
          * <li> Block until signalled or interrupted.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
@@ -2033,9 +2031,8 @@
          * <ol>
          * <li> If current thread is interrupted, throw InterruptedException.
          * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with
-         *      saved state as argument, throwing
-         *      IllegalMonitorStateException if it fails.
+         * <li> Invoke {@link #release} with saved state as argument,
+         *      throwing IllegalMonitorStateException if it fails.
          * <li> Block until signalled, interrupted, or timed out.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
@@ -2048,20 +2045,18 @@
                 throw new InterruptedException();
             Node node = addConditionWaiter();
             int savedState = fullyRelease(node);
-            long lastTime = System.nanoTime();
+            final long deadline = System.nanoTime() + nanosTimeout;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
                 if (nanosTimeout <= 0L) {
                     transferAfterCancelledWait(node);
                     break;
                 }
-                LockSupport.parkNanos(this, nanosTimeout);
+                if (nanosTimeout >= spinForTimeoutThreshold)
+                    LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
-
-                long now = System.nanoTime();
-                nanosTimeout -= now - lastTime;
-                lastTime = now;
+                nanosTimeout = deadline - System.nanoTime();
             }
             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                 interruptMode = REINTERRUPT;
@@ -2069,7 +2064,7 @@
                 unlinkCancelledWaiters();
             if (interruptMode != 0)
                 reportInterruptAfterWait(interruptMode);
-            return nanosTimeout - (System.nanoTime() - lastTime);
+            return deadline - System.nanoTime();
         }
 
         /**
@@ -2077,9 +2072,8 @@
          * <ol>
          * <li> If current thread is interrupted, throw InterruptedException.
          * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with
-         *      saved state as argument, throwing
-         *      IllegalMonitorStateException if it fails.
+         * <li> Invoke {@link #release} with saved state as argument,
+         *      throwing IllegalMonitorStateException if it fails.
          * <li> Block until signalled, interrupted, or timed out.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
@@ -2089,8 +2083,6 @@
          */
         public final boolean awaitUntil(Date deadline)
                 throws InterruptedException {
-            if (deadline == null)
-                throw new NullPointerException();
             long abstime = deadline.getTime();
             if (Thread.interrupted())
                 throw new InterruptedException();
@@ -2121,9 +2113,8 @@
          * <ol>
          * <li> If current thread is interrupted, throw InterruptedException.
          * <li> Save lock state returned by {@link #getState}.
-         * <li> Invoke {@link #release} with
-         *      saved state as argument, throwing
-         *      IllegalMonitorStateException if it fails.
+         * <li> Invoke {@link #release} with saved state as argument,
+         *      throwing IllegalMonitorStateException if it fails.
          * <li> Block until signalled, interrupted, or timed out.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
@@ -2133,14 +2124,12 @@
          */
         public final boolean await(long time, TimeUnit unit)
                 throws InterruptedException {
-            if (unit == null)
-                throw new NullPointerException();
             long nanosTimeout = unit.toNanos(time);
             if (Thread.interrupted())
                 throw new InterruptedException();
             Node node = addConditionWaiter();
             int savedState = fullyRelease(node);
-            long lastTime = System.nanoTime();
+            final long deadline = System.nanoTime() + nanosTimeout;
             boolean timedout = false;
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
@@ -2152,9 +2141,7 @@
                     LockSupport.parkNanos(this, nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
-                long now = System.nanoTime();
-                nanosTimeout -= now - lastTime;
-                lastTime = now;
+                nanosTimeout = deadline - System.nanoTime();
             }
             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                 interruptMode = REINTERRUPT;
diff --git a/luni/src/main/java/java/util/concurrent/locks/Condition.java b/luni/src/main/java/java/util/concurrent/locks/Condition.java
index 7050df9..522e9e2 100644
--- a/luni/src/main/java/java/util/concurrent/locks/Condition.java
+++ b/luni/src/main/java/java/util/concurrent/locks/Condition.java
@@ -5,7 +5,7 @@
  */
 
 package java.util.concurrent.locks;
-import java.util.concurrent.*;
+import java.util.concurrent.TimeUnit;
 import java.util.Date;
 
 /**
@@ -295,7 +295,7 @@
      *   }
      * }}</pre>
      *
-     * <p> Design note: This method requires a nanosecond argument so
+     * <p>Design note: This method requires a nanosecond argument so
      * as to avoid truncation errors in reporting remaining times.
      * Such precision loss would make it difficult for programmers to
      * ensure that total waiting times are not systematically shorter
diff --git a/luni/src/main/java/java/util/concurrent/locks/Lock.java b/luni/src/main/java/java/util/concurrent/locks/Lock.java
index d5c6294..6eeb236 100644
--- a/luni/src/main/java/java/util/concurrent/locks/Lock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/Lock.java
@@ -91,8 +91,9 @@
  *
  * <p>All {@code Lock} implementations <em>must</em> enforce the same
  * memory synchronization semantics as provided by the built-in monitor
- * lock, as described in <a href="http://java.sun.com/docs/books/jls/">
- * The Java Language Specification, Third Edition (17.4 Memory Model)</a>:
+ * lock, as described in
+ * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4">
+ * The Java Language Specification (17.4 Memory Model)</a>:
  * <ul>
  * <li>A successful {@code lock} operation has the same memory
  * synchronization effects as a successful <em>Lock</em> action.
@@ -106,7 +107,7 @@
  *
  * <h3>Implementation Considerations</h3>
  *
- * <p> The three forms of lock acquisition (interruptible,
+ * <p>The three forms of lock acquisition (interruptible,
  * non-interruptible, and timed) may differ in their performance
  * characteristics, ordering guarantees, or other implementation
  * qualities.  Further, the ability to interrupt the <em>ongoing</em>
@@ -197,7 +198,7 @@
      *
      * @throws InterruptedException if the current thread is
      *         interrupted while acquiring the lock (and interruption
-     *         of lock acquisition is supported).
+     *         of lock acquisition is supported)
      */
     void lockInterruptibly() throws InterruptedException;
 
diff --git a/luni/src/main/java/java/util/concurrent/locks/LockSupport.java b/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
index 422e428..875b2bf 100644
--- a/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
+++ b/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
@@ -7,7 +7,6 @@
 package java.util.concurrent.locks;
 import sun.misc.Unsafe;
 
-
 /**
  * Basic thread blocking primitives for creating locks and other
  * synchronization classes.
@@ -73,14 +72,14 @@
  *     // Block while not first in queue or cannot acquire lock
  *     while (waiters.peek() != current ||
  *            !locked.compareAndSet(false, true)) {
- *        LockSupport.park(this);
- *        if (Thread.interrupted()) // ignore interrupts while waiting
- *          wasInterrupted = true;
+ *       LockSupport.park(this);
+ *       if (Thread.interrupted()) // ignore interrupts while waiting
+ *         wasInterrupted = true;
  *     }
  *
  *     waiters.remove();
  *     if (wasInterrupted)          // reassert interrupt status on exit
- *        current.interrupt();
+ *       current.interrupt();
  *   }
  *
  *   public void unlock() {
@@ -89,7 +88,6 @@
  *   }
  * }}</pre>
  */
-
 public class LockSupport {
     private LockSupport() {} // Cannot be instantiated.
 
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java b/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
index bb7b388..8690355 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
@@ -7,16 +7,16 @@
 package java.util.concurrent.locks;
 
 /**
- * A <tt>ReadWriteLock</tt> maintains a pair of associated {@link
+ * A {@code ReadWriteLock} maintains a pair of associated {@link
  * Lock locks}, one for read-only operations and one for writing.
  * The {@link #readLock read lock} may be held simultaneously by
  * multiple reader threads, so long as there are no writers.  The
  * {@link #writeLock write lock} is exclusive.
  *
- * <p>All <tt>ReadWriteLock</tt> implementations must guarantee that
- * the memory synchronization effects of <tt>writeLock</tt> operations
+ * <p>All {@code ReadWriteLock} implementations must guarantee that
+ * the memory synchronization effects of {@code writeLock} operations
  * (as specified in the {@link Lock} interface) also hold with respect
- * to the associated <tt>readLock</tt>. That is, a thread successfully
+ * to the associated {@code readLock}. That is, a thread successfully
  * acquiring the read lock will see all updates made upon previous
  * release of the write lock.
  *
@@ -91,14 +91,14 @@
     /**
      * Returns the lock used for reading.
      *
-     * @return the lock used for reading.
+     * @return the lock used for reading
      */
     Lock readLock();
 
     /**
      * Returns the lock used for writing.
      *
-     * @return the lock used for writing.
+     * @return the lock used for writing
      */
     Lock writeLock();
 }
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java b/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
index 07baf41..bde4741 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
@@ -5,8 +5,8 @@
  */
 
 package java.util.concurrent.locks;
-import java.util.*;
-import java.util.concurrent.*;
+import java.util.concurrent.TimeUnit;
+import java.util.Collection;
 
 /**
  * A reentrant mutual exclusion {@link Lock} with the same basic
@@ -35,7 +35,7 @@
  * fair lock may obtain it multiple times in succession while other
  * active threads are not progressing and not currently holding the
  * lock.
- * Also note that the untimed {@link #tryLock() tryLock} method does not
+ * Also note that the untimed {@link #tryLock()} method does not
  * honor the fairness setting. It will succeed if the lock
  * is available even if other threads are waiting.
  *
@@ -59,10 +59,9 @@
  * }}</pre>
  *
  * <p>In addition to implementing the {@link Lock} interface, this
- * class defines methods {@code isLocked} and
- * {@code getLockQueueLength}, as well as some associated
- * {@code protected} access methods that may be useful for
- * instrumentation and monitoring.
+ * class defines a number of {@code public} and {@code protected}
+ * methods for inspecting the state of the lock.  Some of these
+ * methods are only useful for instrumentation and monitoring.
  *
  * <p>Serialization of this class behaves in the same way as built-in
  * locks: a deserialized lock is in the unlocked state, regardless of
@@ -95,9 +94,8 @@
         abstract void lock();
 
         /**
-         * Performs non-fair tryLock.  tryAcquire is
-         * implemented in subclasses, but both need nonfair
-         * try for trylock method.
+         * Performs non-fair tryLock.  tryAcquire is implemented in
+         * subclasses, but both need nonfair try for trylock method.
          */
         final boolean nonfairTryAcquire(int acquires) {
             final Thread current = Thread.currentThread();
@@ -156,8 +154,7 @@
         }
 
         /**
-         * Reconstitutes this lock instance from a stream.
-         * @param s the stream
+         * Reconstitutes the instance from a stream (that is, deserializes it).
          */
         private void readObject(java.io.ObjectInputStream s)
             throws java.io.IOException, ClassNotFoundException {
@@ -325,7 +322,7 @@
      * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
      * which is almost equivalent (it also detects interruption).
      *
-     * <p> If the current thread already holds this lock then the hold
+     * <p>If the current thread already holds this lock then the hold
      * count is incremented by one and the method returns {@code true}.
      *
      * <p>If the lock is held by another thread then this method will return
@@ -410,7 +407,6 @@
      *         the lock could be acquired
      * @throws InterruptedException if the current thread is interrupted
      * @throws NullPointerException if the time unit is null
-     *
      */
     public boolean tryLock(long timeout, TimeUnit unit)
             throws InterruptedException {
@@ -605,7 +601,6 @@
         return sync.hasQueuedThreads();
     }
 
-
     /**
      * Queries whether the given thread is waiting to acquire this
      * lock. Note that because cancellations may occur at any time, a
@@ -621,7 +616,6 @@
         return sync.isQueued(thread);
     }
 
-
     /**
      * Returns an estimate of the number of threads waiting to
      * acquire this lock.  The value is only an estimate because the number of
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java b/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
index 244a4a7..2d3c65d 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
@@ -5,8 +5,8 @@
  */
 
 package java.util.concurrent.locks;
-import java.util.concurrent.*;
-import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.Collection;
 
 /**
  * An implementation of {@link ReadWriteLock} supporting similar
@@ -16,7 +16,7 @@
  * <ul>
  * <li><b>Acquisition order</b>
  *
- * <p> This class does not impose a reader or writer preference
+ * <p>This class does not impose a reader or writer preference
  * ordering for lock access.  However, it does support an optional
  * <em>fairness</em> policy.
  *
@@ -30,7 +30,7 @@
  * <p>
  *
  * <dt><b><i>Fair mode</i></b>
- * <dd> When constructed as fair, threads contend for entry using an
+ * <dd>When constructed as fair, threads contend for entry using an
  * approximately arrival-order policy. When the currently held lock
  * is released, either the longest-waiting single writer thread will
  * be assigned the write lock, or if there is a group of reader threads
@@ -183,7 +183,6 @@
  *
  * @since 1.5
  * @author Doug Lea
- *
  */
 public class ReentrantReadWriteLock
         implements ReadWriteLock, java.io.Serializable {
@@ -624,10 +623,7 @@
         }
 
         /**
-         * Reconstitutes this lock instance from a stream (that is,
-         * deserializes it).
-         *
-         * @param s the stream
+         * Reconstitutes the instance from a stream (that is, deserializes it).
          */
         private void readObject(java.io.ObjectInputStream s)
             throws java.io.IOException, ClassNotFoundException {
@@ -771,7 +767,7 @@
          *
          * @return {@code true} if the read lock was acquired
          */
-        public  boolean tryLock() {
+        public boolean tryLock() {
             return sync.tryReadLock();
         }
 
@@ -841,7 +837,6 @@
          * @return {@code true} if the read lock was acquired
          * @throws InterruptedException if the current thread is interrupted
          * @throws NullPointerException if the time unit is null
-         *
          */
         public boolean tryLock(long timeout, TimeUnit unit)
                 throws InterruptedException {
@@ -851,10 +846,10 @@
         /**
          * Attempts to release this lock.
          *
-         * <p> If the number of readers is now zero then the lock
+         * <p>If the number of readers is now zero then the lock
          * is made available for write lock attempts.
          */
-        public  void unlock() {
+        public void unlock() {
             sync.releaseShared(1);
         }
 
@@ -993,7 +988,7 @@
          * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
          * which is almost equivalent (it also detects interruption).
          *
-         * <p> If the current thread already holds this lock then the
+         * <p>If the current thread already holds this lock then the
          * hold count is incremented by one and the method returns
          * {@code true}.
          *
@@ -1086,7 +1081,6 @@
          *
          * @throws InterruptedException if the current thread is interrupted
          * @throws NullPointerException if the time unit is null
-         *
          */
         public boolean tryLock(long timeout, TimeUnit unit)
                 throws InterruptedException {
@@ -1103,7 +1097,7 @@
          * IllegalMonitorStateException} is thrown.
          *
          * @throws IllegalMonitorStateException if the current thread does not
-         * hold this lock.
+         * hold this lock
          */
         public void unlock() {
             sync.release(1);
@@ -1231,7 +1225,7 @@
      * Queries the number of read locks held for this lock. This
      * method is designed for use in monitoring system state, not for
      * synchronization control.
-     * @return the number of read locks held.
+     * @return the number of read locks held
      */
     public int getReadLockCount() {
         return sync.getReadLockCount();
diff --git a/luni/src/main/java/java/util/concurrent/package-info.java b/luni/src/main/java/java/util/concurrent/package-info.java
index 155d1b8..51a29e8 100644
--- a/luni/src/main/java/java/util/concurrent/package-info.java
+++ b/luni/src/main/java/java/util/concurrent/package-info.java
@@ -5,7 +5,7 @@
  */
 
 // BEGIN android-note
-// omit links to ForkJoinPool, ForkJoinTask, LinkedTransferQueue, PHaser, TransferQueue
+// omit links to ForkJoinPool, ForkJoinTask, LinkedTransferQueue, Phaser, TransferQueue
 // END android-note
 
 /**
@@ -23,7 +23,7 @@
  *
  * {@link java.util.concurrent.Executor} is a simple standardized
  * interface for defining custom thread-like subsystems, including
- * thread pools, asynchronous IO, and lightweight task frameworks.
+ * thread pools, asynchronous I/O, and lightweight task frameworks.
  * Depending on which concrete Executor class is being used, tasks may
  * execute in a newly created thread, an existing task-execution thread,
  * or the thread calling {@link java.util.concurrent.Executor#execute
@@ -174,7 +174,7 @@
  * it may (or may not) reflect any updates since the iterator was
  * created.
  *
- * <h2><a name="MemoryVisibility">Memory Consistency Properties</a></h2>
+ * <h2 id="MemoryVisibility">Memory Consistency Properties</h2>
  *
  * <a href="http://java.sun.com/docs/books/jls/third_edition/html/memory.html">
  * Chapter 17 of the Java Language Specification</a> defines the
@@ -243,8 +243,7 @@
  *   in each thread <i>happen-before</i> those subsequent to the
  *   corresponding {@code exchange()} in another thread.
  *
- *   <li>Actions prior to calling {@code CyclicBarrier.await} and
- *   {@code Phaser.awaitAdvance} (as well as its variants)
+ *   <li>Actions prior to calling {@code CyclicBarrier.await}
  *   <i>happen-before</i> actions performed by the barrier action, and
  *   actions performed by the barrier action <i>happen-before</i> actions
  *   subsequent to a successful return from the corresponding {@code await}
diff --git a/luni/src/main/java/java/util/jar/Attributes.java b/luni/src/main/java/java/util/jar/Attributes.java
index 48008ce..7e32897 100644
--- a/luni/src/main/java/java/util/jar/Attributes.java
+++ b/luni/src/main/java/java/util/jar/Attributes.java
@@ -50,8 +50,6 @@
      * </pre>
      */
     public static class Name {
-        private final String name;
-
         /** The class path (a main attribute). */
         public static final Name CLASS_PATH = new Name("Class-Path");
 
@@ -140,7 +138,12 @@
          */
         public static final Name IMPLEMENTATION_URL = new Name("Implementation-URL");
 
-        static final Name NAME = new Name("Name");
+        /**
+         * @hide
+         */
+        public static final Name NAME = new Name("Name");
+
+        private final String name;
 
         public Name(String name) {
             // encoded name + "\r\n" must be <= 72 bytes; ASCII-only so byte count equals char count
@@ -409,20 +412,16 @@
      *         valid key.
      */
     public String getValue(String name) {
-        return (String) map.get(new Attributes.Name(name));
+        return getValue(new Attributes.Name(name));
     }
 
     /**
-     * Stores the value {@code val} associated with the key {@code name} in this
+     * Stores the value {@code value} associated with the key {@code name} in this
      * {@code Attributes}.
      *
-     * @param name
-     *            the key to store.
-     * @param val
-     *            the value to store in this {@code Attributes}.
      * @return the value being stored.
      */
-    public String putValue(String name, String val) {
-        return (String) map.put(new Attributes.Name(name), val);
+    public String putValue(String name, String value) {
+        return (String) map.put(new Attributes.Name(name), value);
     }
 }
diff --git a/luni/src/main/java/java/util/jar/JarFile.java b/luni/src/main/java/java/util/jar/JarFile.java
index 178688f..5293a89 100644
--- a/luni/src/main/java/java/util/jar/JarFile.java
+++ b/luni/src/main/java/java/util/jar/JarFile.java
@@ -98,18 +98,18 @@
         }
 
         @Override
-        public int read(byte[] buf, int off, int nbytes) throws IOException {
+        public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
             if (done) {
                 return -1;
             }
             if (count > 0) {
-                int r = super.read(buf, off, nbytes);
+                int r = super.read(buffer, byteOffset, byteCount);
                 if (r != -1) {
                     int size = r;
                     if (count < size) {
                         size = (int) count;
                     }
-                    entry.write(buf, off, size);
+                    entry.write(buffer, byteOffset, size);
                     count -= size;
                 } else {
                     count = 0;
diff --git a/luni/src/main/java/java/util/jar/JarInputStream.java b/luni/src/main/java/java/util/jar/JarInputStream.java
index 03f765f..5e08b5d 100644
--- a/luni/src/main/java/java/util/jar/JarInputStream.java
+++ b/luni/src/main/java/java/util/jar/JarInputStream.java
@@ -130,25 +130,18 @@
     }
 
     /**
-     * Reads up to {@code length} of decompressed data and stores it in
-     * {@code buffer} starting at {@code offset}.
+     * Reads up to {@code byteCount} bytes of decompressed data and stores it in
+     * {@code buffer} starting at {@code byteOffset}. Returns the number of uncompressed bytes read.
      *
-     * @param buffer
-     *            Buffer to store into
-     * @param offset
-     *            offset in buffer to store at
-     * @param length
-     *            number of bytes to store
-     * @return Number of uncompressed bytes read
      * @throws IOException
      *             if an IOException occurs.
      */
     @Override
-    public int read(byte[] buffer, int offset, int length) throws IOException {
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
         if (mEntry != null) {
             return -1;
         }
-        int r = super.read(buffer, offset, length);
+        int r = super.read(buffer, byteOffset, byteCount);
         if (verStream != null && !eos) {
             if (r == -1) {
                 eos = true;
@@ -168,7 +161,7 @@
                     }
                 }
             } else {
-                verStream.write(buffer, offset, r);
+                verStream.write(buffer, byteOffset, r);
             }
         }
         return r;
diff --git a/luni/src/main/java/java/util/jar/JarVerifier.java b/luni/src/main/java/java/util/jar/JarVerifier.java
index 5e3dd76..8185c6d 100644
--- a/luni/src/main/java/java/util/jar/JarVerifier.java
+++ b/luni/src/main/java/java/util/jar/JarVerifier.java
@@ -20,7 +20,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.security.GeneralSecurityException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -219,7 +219,7 @@
             if (hash == null) {
                 continue;
             }
-            byte[] hashBytes = hash.getBytes(Charsets.ISO_8859_1);
+            byte[] hashBytes = hash.getBytes(StandardCharsets.ISO_8859_1);
 
             try {
                 return new VerifierEntry(name, MessageDigest.getInstance(algorithm), hashBytes,
@@ -289,8 +289,7 @@
      */
     private void verifyCertificate(String certFile) {
         // Found Digital Sig, .SF should already have been read
-        String signatureFile = certFile.substring(0, certFile.lastIndexOf('.'))
-                + ".SF";
+        String signatureFile = certFile.substring(0, certFile.lastIndexOf('.')) + ".SF";
         byte[] sfBytes = metaEntries.get(signatureFile);
         if (sfBytes == null) {
             return;
@@ -328,8 +327,8 @@
         Attributes attributes = new Attributes();
         HashMap<String, Attributes> entries = new HashMap<String, Attributes>();
         try {
-            InitManifest im = new InitManifest(sfBytes, attributes);
-            im.initEntries(entries, null);
+            ManifestReader im = new ManifestReader(sfBytes, attributes);
+            im.readEntries(entries, null);
         } catch (IOException e) {
             return;
         }
@@ -357,12 +356,9 @@
         }
 
         // Use .SF to verify the whole manifest.
-        String digestAttribute = createdBySigntool ? "-Digest"
-                : "-Digest-Manifest";
-        if (!verify(attributes, digestAttribute, manifest, 0, manifest.length,
-                false, false)) {
-            Iterator<Map.Entry<String, Attributes>> it = entries.entrySet()
-                    .iterator();
+        String digestAttribute = createdBySigntool ? "-Digest" : "-Digest-Manifest";
+        if (!verify(attributes, digestAttribute, manifest, 0, manifest.length, false, false)) {
+            Iterator<Map.Entry<String, Attributes>> it = entries.entrySet().iterator();
             while (it.hasNext()) {
                 Map.Entry<String, Attributes> entry = it.next();
                 Manifest.Chunk chunk = man.getChunk(entry.getKey());
@@ -415,14 +411,13 @@
             } catch (NoSuchAlgorithmException e) {
                 continue;
             }
-            if (ignoreSecondEndline && data[end - 1] == '\n'
-                    && data[end - 2] == '\n') {
+            if (ignoreSecondEndline && data[end - 1] == '\n' && data[end - 2] == '\n') {
                 md.update(data, start, end - 1 - start);
             } else {
                 md.update(data, start, end - start);
             }
             byte[] b = md.digest();
-            byte[] hashBytes = hash.getBytes(Charsets.ISO_8859_1);
+            byte[] hashBytes = hash.getBytes(StandardCharsets.ISO_8859_1);
             return MessageDigest.isEqual(b, Base64.decode(hashBytes));
         }
         return ignorable;
diff --git a/luni/src/main/java/java/util/jar/Manifest.java b/luni/src/main/java/java/util/jar/Manifest.java
index 723aa99..b6ebddc 100644
--- a/luni/src/main/java/java/util/jar/Manifest.java
+++ b/luni/src/main/java/java/util/jar/Manifest.java
@@ -25,8 +25,8 @@
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.CharsetEncoder;
-import java.nio.charset.Charsets;
 import java.nio.charset.CoderResult;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -43,8 +43,6 @@
 
     private static final byte[] VALUE_SEPARATOR = new byte[] { ':', ' ' };
 
-    private static final Attributes.Name NAME_ATTRIBUTE = new Attributes.Name("Name");
-
     private static final Field BAIS_BUF = getByteArrayInputStreamField("buf");
     private static final Field BAIS_POS = getByteArrayInputStreamField("pos");
 
@@ -213,9 +211,9 @@
             buf[buf.length - 1] = '\n';
         }
 
-        InitManifest im = new InitManifest(buf, mainAttributes);
-        mainEnd = im.getPos();
-        im.initEntries(entries, chunks);
+        ManifestReader im = new ManifestReader(buf, mainAttributes);
+        mainEnd = im.getEndOfMainSection();
+        im.readEntries(entries, chunks);
     }
 
     /**
@@ -302,7 +300,7 @@
      *             If an error occurs writing the {@code Manifest}.
      */
     static void write(Manifest manifest, OutputStream out) throws IOException {
-        CharsetEncoder encoder = Charsets.UTF_8.newEncoder();
+        CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder();
         ByteBuffer buffer = ByteBuffer.allocate(LINE_LENGTH_LIMIT);
 
         Attributes.Name versionName = Attributes.Name.MANIFEST_VERSION;
@@ -325,7 +323,7 @@
         Iterator<String> i = manifest.getEntries().keySet().iterator();
         while (i.hasNext()) {
             String key = i.next();
-            writeEntry(out, NAME_ATTRIBUTE, key, encoder, buffer);
+            writeEntry(out, Attributes.Name.NAME, key, encoder, buffer);
             Attributes attributes = manifest.entries.get(key);
             Iterator<?> entries = attributes.keySet().iterator();
             while (entries.hasNext()) {
@@ -339,7 +337,7 @@
     private static void writeEntry(OutputStream os, Attributes.Name name,
             String value, CharsetEncoder encoder, ByteBuffer bBuf) throws IOException {
         String nameString = name.getName();
-        os.write(nameString.getBytes(Charsets.US_ASCII));
+        os.write(nameString.getBytes(StandardCharsets.US_ASCII));
         os.write(VALUE_SEPARATOR);
 
         encoder.reset();
diff --git a/luni/src/main/java/java/util/jar/InitManifest.java b/luni/src/main/java/java/util/jar/ManifestReader.java
similarity index 81%
rename from luni/src/main/java/java/util/jar/InitManifest.java
rename to luni/src/main/java/java/util/jar/ManifestReader.java
index ade4790..2faaa90 100644
--- a/luni/src/main/java/java/util/jar/InitManifest.java
+++ b/luni/src/main/java/java/util/jar/ManifestReader.java
@@ -18,35 +18,42 @@
 package java.util.jar;
 
 import java.io.IOException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
 import java.util.Map;
 
 /**
  * Reads a JAR file manifest. The specification is here:
  * http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html
  */
-class InitManifest {
+class ManifestReader {
+    // There are relatively few unique attribute names,
+    // but a manifest might have thousands of entries.
+    private final HashMap<String, Attributes.Name> attributeNameCache = new HashMap<String, Attributes.Name>();
+
+    private final UnsafeByteSequence valueBuffer = new UnsafeByteSequence(80);
+
     private final byte[] buf;
 
+    private final int endOfMainSection;
+
     private int pos;
 
     private Attributes.Name name;
 
     private String value;
 
-    private final UnsafeByteSequence valueBuffer = new UnsafeByteSequence(80);
     private int consecutiveLineBreaks = 0;
 
-    InitManifest(byte[] buf, Attributes main) throws IOException {
+    public ManifestReader(byte[] buf, Attributes main) throws IOException {
         this.buf = buf;
         while (readHeader()) {
             main.put(name, value);
         }
+        this.endOfMainSection = pos;
     }
 
-    void initEntries(Map<String, Attributes> entries,
-            Map<String, Manifest.Chunk> chunks) throws IOException {
-
+    public void readEntries(Map<String, Attributes> entries, Map<String, Manifest.Chunk> chunks) throws IOException {
         int mark = pos;
         while (readHeader()) {
             if (!Attributes.Name.NAME.equals(name)) {
@@ -81,8 +88,8 @@
         }
     }
 
-    int getPos() {
-        return pos;
+    public int getEndOfMainSection() {
+        return endOfMainSection;
     }
 
     /**
@@ -110,14 +117,18 @@
                 continue;
             }
 
-            String name = new String(buf, mark, pos - mark - 1, Charsets.US_ASCII);
+            String nameString = new String(buf, mark, pos - mark - 1, StandardCharsets.US_ASCII);
 
             if (buf[pos++] != ' ') {
-                throw new IOException(String.format("Invalid value for attribute '%s'", name));
+                throw new IOException(String.format("Invalid value for attribute '%s'", nameString));
             }
 
             try {
-                this.name = new Attributes.Name(name);
+                name = attributeNameCache.get(nameString);
+                if (name == null) {
+                    name = new Attributes.Name(nameString);
+                    attributeNameCache.put(nameString, name);
+                }
             } catch (IllegalArgumentException e) {
                 // new Attributes.Name() throws IllegalArgumentException but we declare IOException
                 throw new IOException(e.getMessage());
@@ -164,6 +175,6 @@
         }
 
         valueBuffer.write(buf, mark, last - mark);
-        value = valueBuffer.toString(Charsets.UTF_8);
+        value = valueBuffer.toString(StandardCharsets.UTF_8);
     }
 }
diff --git a/luni/src/main/java/java/util/logging/Logger.java b/luni/src/main/java/java/util/logging/Logger.java
index 1c86dc8..3f2b787 100644
--- a/luni/src/main/java/java/util/logging/Logger.java
+++ b/luni/src/main/java/java/util/logging/Logger.java
@@ -91,8 +91,8 @@
 
     /**
      * The global logger is provided as convenience for casual use.
-     * @deprecated deadlock-prone. Use {@code Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)} as
-     * a direct replacement, but see the discussion of how to use {@code Logger} in the class
+     * @deprecated This is deadlock-prone. Use {@code Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)}
+     * as a direct replacement, but read the discussion of how to use {@link Logger} in the class
      * documentation.
      */
     @Deprecated
@@ -388,7 +388,6 @@
     /**
      * Returns the global {@code Logger}.
      * @since 1.7
-     * @hide 1.7
      */
     public static Logger getGlobal() {
         return global;
diff --git a/luni/src/main/java/java/util/prefs/AbstractPreferences.java b/luni/src/main/java/java/util/prefs/AbstractPreferences.java
index 71110c3..d2cb28e 100644
--- a/luni/src/main/java/java/util/prefs/AbstractPreferences.java
+++ b/luni/src/main/java/java/util/prefs/AbstractPreferences.java
@@ -19,7 +19,7 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.EventListener;
 import java.util.EventObject;
@@ -441,7 +441,7 @@
             return EmptyArray.BYTE;
         }
         try {
-            byte[] bavalue = svalue.getBytes(Charsets.US_ASCII);
+            byte[] bavalue = svalue.getBytes(StandardCharsets.US_ASCII);
             if (bavalue.length % 4 != 0) {
                 return deflt;
             }
diff --git a/luni/src/main/java/java/util/regex/Matcher.java b/luni/src/main/java/java/util/regex/Matcher.java
index 320e14c..d58d092 100644
--- a/luni/src/main/java/java/util/regex/Matcher.java
+++ b/luni/src/main/java/java/util/regex/Matcher.java
@@ -656,6 +656,16 @@
         }
     }
 
+    /**
+     * Returns a string representing this {@code Matcher}.
+     * The format of this string is unspecified.
+     */
+    @Override public String toString() {
+        return getClass().getName() + "[pattern=" + pattern() +
+            " region=" + regionStart() + "," + regionEnd() +
+            " lastmatch=" + (matchFound ? group() : "") + "]";
+    }
+
     private static native void closeImpl(long addr);
     private static native boolean findImpl(long addr, String s, int startIndex, int[] offsets);
     private static native boolean findNextImpl(long addr, String s, int[] offsets);
diff --git a/luni/src/main/java/java/util/regex/Pattern.java b/luni/src/main/java/java/util/regex/Pattern.java
index 44b749e..a33ee93 100644
--- a/luni/src/main/java/java/util/regex/Pattern.java
+++ b/luni/src/main/java/java/util/regex/Pattern.java
@@ -104,8 +104,8 @@
  * prefixed by {@code Is}. For example {@code \p{IsLu}} for all uppercase letters.
  * <li>POSIX class names. These are 'Alnum', 'Alpha', 'ASCII', 'Blank', 'Cntrl', 'Digit',
  * 'Graph', 'Lower', 'Print', 'Punct', 'Upper', 'XDigit'.
- * <li>Unicode block names, as used by {@link java.lang.Character.UnicodeBlock#forName} prefixed
- * by {@code In}. For example {@code \p{InHebrew}} for all characters in the Hebrew block.
+ * <li>Unicode block names, as accepted as input to {@link java.lang.Character.UnicodeBlock#forName},
+ * prefixed by {@code In}. For example {@code \p{InHebrew}} for all characters in the Hebrew block.
  * <li>Character method names. These are all non-deprecated methods from {@link java.lang.Character}
  * whose name starts with {@code is}, but with the {@code is} replaced by {@code java}.
  * For example, {@code \p{javaLowerCase}}.
@@ -385,6 +385,10 @@
         if ((flags & CANON_EQ) != 0) {
             throw new UnsupportedOperationException("CANON_EQ flag not supported");
         }
+        int supportedFlags = CASE_INSENSITIVE | COMMENTS | DOTALL | LITERAL | MULTILINE | UNICODE_CASE | UNIX_LINES;
+        if ((flags & ~supportedFlags) != 0) {
+            throw new IllegalArgumentException("Unsupported flags: " + (flags & ~supportedFlags));
+        }
         this.pattern = pattern;
         this.flags = flags;
         compile();
diff --git a/luni/src/main/java/java/util/zip/CheckedInputStream.java b/luni/src/main/java/java/util/zip/CheckedInputStream.java
index 454098b..da6c635 100644
--- a/luni/src/main/java/java/util/zip/CheckedInputStream.java
+++ b/luni/src/main/java/java/util/zip/CheckedInputStream.java
@@ -68,35 +68,26 @@
     }
 
     /**
-     * Reads up to n bytes of data from the underlying input stream, storing it
-     * into {@code buf}, starting at offset {@code off}. The checksum is
+     * Reads up to {@code byteCount} bytes of data from the underlying input stream, storing it
+     * into {@code buffer}, starting at offset {@code byteOffset}. The checksum is
      * updated with the bytes read.
+     * Returns the number of bytes actually read or {@code -1} if arrived at the
+     * end of the filtered stream while reading the data.
      *
-     * @param buf
-     *            the byte array in which to store the bytes read.
-     * @param off
-     *            the initial position in {@code buf} to store the bytes read
-     *            from this stream.
-     * @param nbytes
-     *            the maximum number of bytes to store in {@code buf}.
-     * @return the number of bytes actually read or {@code -1} if arrived at the
-     *         end of the filtered stream while reading the data.
      * @throws IOException
      *             if this stream is closed or some I/O error occurs.
      */
     @Override
-    public int read(byte[] buf, int off, int nbytes) throws IOException {
-        int x = in.read(buf, off, nbytes);
-        if (x != -1) {
-            check.update(buf, off, x);
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+        int bytesRead = in.read(buffer, byteOffset, byteCount);
+        if (bytesRead != -1) {
+            check.update(buffer, byteOffset, bytesRead);
         }
-        return x;
+        return bytesRead;
     }
 
     /**
      * Returns the checksum calculated on the stream read so far.
-     *
-     * @return the updated checksum.
      */
     public Checksum getChecksum() {
         return check;
diff --git a/luni/src/main/java/java/util/zip/Deflater.java b/luni/src/main/java/java/util/zip/Deflater.java
index d96ab2a..3365031 100644
--- a/luni/src/main/java/java/util/zip/Deflater.java
+++ b/luni/src/main/java/java/util/zip/Deflater.java
@@ -106,8 +106,6 @@
 
     /**
      * Use buffering for best compression.
-     *
-     * @hide
      * @since 1.7
      */
     public static final int NO_FLUSH = 0;
@@ -115,8 +113,6 @@
     /**
      * Flush buffers so recipients can immediately decode the data sent thus
      * far. This mode may degrade compression.
-     *
-     * @hide
      * @since 1.7
      */
     public static final int SYNC_FLUSH = 2;
@@ -126,8 +122,6 @@
      * far. The compression state is also reset to permit random access and
      * recovery for clients who have discarded or damaged their own copy. This
      * mode may degrade compression.
-     *
-     * @hide
      * @since 1.7
      */
     public static final int FULL_FLUSH = 3;
@@ -228,7 +222,7 @@
      *      may have exceeded the output buffer's capacity. In this case,
      *      finishing a flush will require the output buffer to be drained
      *      and additional calls to {@link #deflate} to be made.
-     * @hide
+     * @throws IllegalArgumentException if {@code flush} is invalid.
      * @since 1.7
      */
     public synchronized int deflate(byte[] buf, int offset, int byteCount, int flush) {
diff --git a/luni/src/main/java/java/util/zip/DeflaterInputStream.java b/luni/src/main/java/java/util/zip/DeflaterInputStream.java
index d854fec..f987e39a 100644
--- a/luni/src/main/java/java/util/zip/DeflaterInputStream.java
+++ b/luni/src/main/java/java/util/zip/DeflaterInputStream.java
@@ -106,14 +106,14 @@
     }
 
     /**
-     * Reads compressed data into a byte buffer. The result will be bytes of compressed
+     * Reads up to {@code byteCount} bytes of compressed data into a byte buffer. The result will be bytes of compressed
      * data corresponding to an uncompressed byte or bytes read from the underlying stream.
-     * @return the number of bytes read or -1 if the end of the compressed input
-     *         stream has been reached.
+     * Returns the number of bytes read or -1 if the end of the compressed input
+     * stream has been reached.
      */
-    @Override public int read(byte[] buffer, int offset, int byteCount) throws IOException {
+    @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
         checkClosed();
-        Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
         if (byteCount == 0) {
             return 0;
         }
@@ -137,7 +137,7 @@
             if (bytesDeflated == -1) {
                 break;
             }
-            System.arraycopy(buf, 0, buffer, offset + count, bytesDeflated);
+            System.arraycopy(buf, 0, buffer, byteOffset + count, bytesDeflated);
             count += bytesDeflated;
         }
         if (count == 0) {
diff --git a/luni/src/main/java/java/util/zip/DeflaterOutputStream.java b/luni/src/main/java/java/util/zip/DeflaterOutputStream.java
index 448f61c..6cce5a5 100644
--- a/luni/src/main/java/java/util/zip/DeflaterOutputStream.java
+++ b/luni/src/main/java/java/util/zip/DeflaterOutputStream.java
@@ -48,53 +48,28 @@
     private final boolean syncFlush;
 
     /**
-     * This constructor lets you pass the {@code Deflater} specifying the
-     * compression algorithm.
-     *
-     * @param os
-     *            is the {@code OutputStream} where to write the compressed data
-     *            to.
-     * @param def
-     *            is the specific {@code Deflater} that is used to compress
-     *            data.
-     */
-    public DeflaterOutputStream(OutputStream os, Deflater def) {
-        this(os, def, BUF_SIZE, false);
-    }
-
-    /**
-     * This is the most basic constructor. You only need to pass the {@code
-     * OutputStream} to which the compressed data shall be written to. The
-     * default settings for the {@code Deflater} and internal buffer are used.
-     * In particular the {@code Deflater} produces a ZLIB header in the output
-     * stream.
-     *
-     * @param os
-     *            is the OutputStream where to write the compressed data to.
+     * Constructs a new instance with a default-constructed {@link Deflater}.
      */
     public DeflaterOutputStream(OutputStream os) {
         this(os, new Deflater(), BUF_SIZE, false);
     }
 
     /**
-     * This constructor lets you specify both the compression algorithm as well
-     * as the internal buffer size to be used.
-     *
-     * @param os
-     *            is the {@code OutputStream} where to write the compressed data
-     *            to.
-     * @param def
-     *            is the specific {@code Deflater} that will be used to compress
-     *            data.
-     * @param bufferSize
-     *            is the size to be used for the internal buffer.
+     * Constructs a new instance with the given {@code Deflater}.
+     */
+    public DeflaterOutputStream(OutputStream os, Deflater def) {
+        this(os, def, BUF_SIZE, false);
+    }
+
+    /**
+     * Constructs a new instance with the given {@code Deflater} and buffer size.
      */
     public DeflaterOutputStream(OutputStream os, Deflater def, int bufferSize) {
         this(os, def, bufferSize, false);
     }
 
     /**
-     * @hide
+     * Constructs a new instance with the given flushing behavior (see {@link #flush}).
      * @since 1.7
      */
     public DeflaterOutputStream(OutputStream os, boolean syncFlush) {
@@ -102,7 +77,8 @@
     }
 
     /**
-     * @hide
+     * Constructs a new instance with the given {@code Deflater} and
+     * flushing behavior (see {@link #flush}).
      * @since 1.7
      */
     public DeflaterOutputStream(OutputStream os, Deflater def, boolean syncFlush) {
@@ -110,7 +86,8 @@
     }
 
     /**
-     * @hide
+     * Constructs a new instance with the given {@code Deflater}, buffer size, and
+     * flushing behavior (see {@link #flush}).
      * @since 1.7
      */
     public DeflaterOutputStream(OutputStream os, Deflater def, int bufferSize, boolean syncFlush) {
@@ -206,10 +183,9 @@
      * Flushes the underlying stream. This flushes only the bytes that can be
      * compressed at the highest level.
      *
-     * <p>For deflater output streams constructed with Java 7's
-     * {@code syncFlush} parameter set to true (not yet available on Android),
-     * this first flushes all outstanding data so that it may be immediately
-     * read by its recipient. Doing so may degrade compression.
+     * <p>For deflater output streams constructed with the {@code syncFlush} parameter set to true,
+     * this first flushes all outstanding data so that it may be immediately read by its recipient.
+     * Doing so may degrade compression but improve interactive behavior.
      */
     @Override public void flush() throws IOException {
         if (syncFlush) {
diff --git a/luni/src/main/java/java/util/zip/GZIPInputStream.java b/luni/src/main/java/java/util/zip/GZIPInputStream.java
index fd73acc..08599ea 100644
--- a/luni/src/main/java/java/util/zip/GZIPInputStream.java
+++ b/luni/src/main/java/java/util/zip/GZIPInputStream.java
@@ -148,29 +148,25 @@
         super.close();
     }
 
-    /**
-     * Reads and decompresses GZIP data from the underlying stream into the
-     * given buffer.
-     */
     @Override
-    public int read(byte[] buffer, int offset, int byteCount) throws IOException {
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
         if (closed) {
             throw new IOException("Stream is closed");
         }
         if (eos) {
             return -1;
         }
-        Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
 
         int bytesRead;
         try {
-            bytesRead = super.read(buffer, offset, byteCount);
+            bytesRead = super.read(buffer, byteOffset, byteCount);
         } finally {
             eos = eof; // update eos after every read(), even when it throws
         }
 
         if (bytesRead != -1) {
-            crc.update(buffer, offset, bytesRead);
+            crc.update(buffer, byteOffset, bytesRead);
         }
 
         if (eos) {
diff --git a/luni/src/main/java/java/util/zip/GZIPOutputStream.java b/luni/src/main/java/java/util/zip/GZIPOutputStream.java
index 7d30ae8..8dd907b 100644
--- a/luni/src/main/java/java/util/zip/GZIPOutputStream.java
+++ b/luni/src/main/java/java/util/zip/GZIPOutputStream.java
@@ -47,32 +47,39 @@
     protected CRC32 crc = new CRC32();
 
     /**
-     * Construct a new {@code GZIPOutputStream} to write data in GZIP format to
-     * the underlying stream.
-     *
-     * @param os
-     *            the {@code OutputStream} to write data to.
-     * @throws IOException
-     *             if an {@code IOException} occurs.
+     * Constructs a new {@code GZIPOutputStream} to write data in GZIP format to
+     * the given stream.
      */
     public GZIPOutputStream(OutputStream os) throws IOException {
-        this(os, BUF_SIZE);
+        this(os, BUF_SIZE, true);
     }
 
     /**
-     * Construct a new {@code GZIPOutputStream} to write data in GZIP format to
-     * the underlying stream. Set the internal compression buffer to size
-     * {@code size}.
-     *
-     * @param os
-     *            the {@code OutputStream} to write to.
-     * @param size
-     *            the internal buffer size.
-     * @throws IOException
-     *             if an {@code IOException} occurs.
+     * Constructs a new {@code GZIPOutputStream} to write data in GZIP format to
+     * the given stream with the given flushing behavior (see {@link DeflaterOutputStream#flush}).
+     * @since 1.7
      */
-    public GZIPOutputStream(OutputStream os, int size) throws IOException {
-        super(os, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size);
+    public GZIPOutputStream(OutputStream os, boolean syncFlush) throws IOException {
+        this(os, BUF_SIZE, syncFlush);
+    }
+
+    /**
+     * Constructs a new {@code GZIPOutputStream} to write data in GZIP format to
+     * the given stream with the given internal buffer size and
+     * flushing behavior (see {@link DeflaterOutputStream#flush}).
+     */
+    public GZIPOutputStream(OutputStream os, int bufferSize) throws IOException {
+        this(os, bufferSize, true);
+    }
+
+    /**
+     * Constructs a new {@code GZIPOutputStream} to write data in GZIP format to
+     * the given stream with the given internal buffer size and
+     * flushing behavior (see {@link DeflaterOutputStream#flush}).
+     * @since 1.7
+     */
+    public GZIPOutputStream(OutputStream os, int bufferSize, boolean syncFlush) throws IOException {
+        super(os, new Deflater(Deflater.DEFAULT_COMPRESSION, true), bufferSize, syncFlush);
         writeShort(GZIPInputStream.GZIP_MAGIC);
         out.write(Deflater.DEFLATED);
         out.write(0); // flags
diff --git a/luni/src/main/java/java/util/zip/InflaterInputStream.java b/luni/src/main/java/java/util/zip/InflaterInputStream.java
index 371c80a..25b2fe8 100644
--- a/luni/src/main/java/java/util/zip/InflaterInputStream.java
+++ b/luni/src/main/java/java/util/zip/InflaterInputStream.java
@@ -132,14 +132,13 @@
 
     /**
      * Reads up to {@code byteCount} bytes of decompressed data and stores it in
-     * {@code buffer} starting at {@code offset}.
-     *
-     * @return Number of uncompressed bytes read
+     * {@code buffer} starting at {@code byteOffset}. Returns the number of uncompressed bytes read,
+     * or -1.
      */
     @Override
-    public int read(byte[] buffer, int offset, int byteCount) throws IOException {
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
         checkClosed();
-        Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
 
         if (byteCount == 0) {
             return 0;
@@ -156,7 +155,7 @@
             // Invariant: if reading returns -1 or throws, eof must be true.
             // It may also be true if the next read() should return -1.
             try {
-                int result = inf.inflate(buffer, offset, byteCount);
+                int result = inf.inflate(buffer, byteOffset, byteCount);
                 eof = inf.finished();
                 if (result > 0) {
                     return result;
diff --git a/luni/src/main/java/java/util/zip/ZipEntry.java b/luni/src/main/java/java/util/zip/ZipEntry.java
index e9168b5..e91c73e 100644
--- a/luni/src/main/java/java/util/zip/ZipEntry.java
+++ b/luni/src/main/java/java/util/zip/ZipEntry.java
@@ -20,7 +20,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteOrder;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
@@ -185,7 +185,7 @@
             return;
         }
 
-        byte[] commentBytes = comment.getBytes(Charsets.UTF_8);
+        byte[] commentBytes = comment.getBytes(StandardCharsets.UTF_8);
         if (commentBytes.length > 0xffff) {
             throw new IllegalArgumentException("Comment too long: " + commentBytes.length);
         }
@@ -387,14 +387,14 @@
         if (containsNulByte(nameBytes)) {
             throw new ZipException("Filename contains NUL byte: " + Arrays.toString(nameBytes));
         }
-        name = new String(nameBytes, 0, nameBytes.length, Charsets.UTF_8);
+        name = new String(nameBytes, 0, nameBytes.length, StandardCharsets.UTF_8);
 
         // The RI has always assumed UTF-8. (If GPBF_UTF8_FLAG isn't set, the encoding is
         // actually IBM-437.)
         if (commentByteCount > 0) {
             byte[] commentBytes = new byte[commentByteCount];
             Streams.readFully(in, commentBytes, 0, commentByteCount);
-            comment = new String(commentBytes, 0, commentBytes.length, Charsets.UTF_8);
+            comment = new String(commentBytes, 0, commentBytes.length, StandardCharsets.UTF_8);
         }
 
         if (extraLength > 0) {
diff --git a/luni/src/main/java/java/util/zip/ZipFile.java b/luni/src/main/java/java/util/zip/ZipFile.java
index 519459b..47bc48e 100644
--- a/luni/src/main/java/java/util/zip/ZipFile.java
+++ b/luni/src/main/java/java/util/zip/ZipFile.java
@@ -19,6 +19,7 @@
 
 import dalvik.system.CloseGuard;
 import java.io.BufferedInputStream;
+import java.io.Closeable;
 import java.io.EOFException;
 import java.io.DataInputStream;
 import java.io.File;
@@ -26,6 +27,7 @@
 import java.io.InputStream;
 import java.io.RandomAccessFile;
 import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -45,7 +47,7 @@
  * <p>If you want to create a zip file, use {@link ZipOutputStream}. There is no API for updating
  * an existing zip file.
  */
-public class ZipFile implements ZipConstants {
+public class ZipFile implements Closeable, ZipConstants {
     /**
      * General Purpose Bit Flags, Bit 0.
      * If set, indicates that the file is encrypted.
@@ -101,6 +103,8 @@
 
     private final LinkedHashMap<String, ZipEntry> entries = new LinkedHashMap<String, ZipEntry>();
 
+    private String comment;
+
     private final CloseGuard guard = CloseGuard.get();
 
     /**
@@ -220,6 +224,18 @@
     }
 
     /**
+     * Returns this file's comment, or null if it doesn't have one.
+     * See {@link ZipOutputStream#setComment}.
+     *
+     * @throws IllegalStateException if this zip file has been closed.
+     * @since 1.7
+     */
+    public String getComment() {
+        checkNotClosed();
+        return comment;
+    }
+
+    /**
      * Returns the zip entry with the given name, or null if there is no such entry.
      *
      * @throws IllegalStateException if this zip file has been closed.
@@ -351,9 +367,9 @@
             }
         }
 
-        // Read the End Of Central Directory. We could use ENDHDR instead of the magic number 18,
-        // but we don't actually need all the header.
-        byte[] eocd = new byte[18];
+        // Read the End Of Central Directory. ENDHDR includes the signature bytes,
+        // which we've already read.
+        byte[] eocd = new byte[ENDHDR - 4];
         raf.readFully(eocd);
 
         // Pull out the information we need.
@@ -364,11 +380,18 @@
         int totalNumEntries = it.readShort() & 0xffff;
         it.skip(4); // Ignore centralDirSize.
         long centralDirOffset = ((long) it.readInt()) & 0xffffffffL;
+        int commentLength = it.readShort() & 0xffff;
 
         if (numEntries != totalNumEntries || diskNumber != 0 || diskWithCentralDir != 0) {
             throw new ZipException("spanned archives not supported");
         }
 
+        if (commentLength > 0) {
+            byte[] commentBytes = new byte[commentLength];
+            raf.readFully(commentBytes);
+            comment = new String(commentBytes, 0, commentBytes.length, StandardCharsets.UTF_8);
+        }
+
         // Seek to the first CDE and read all entries.
         // We have to do this now (from the constructor) rather than lazily because the
         // public API doesn't allow us to throw IOException except from the constructor
@@ -412,13 +435,13 @@
             return Streams.readSingleByte(this);
         }
 
-        @Override public int read(byte[] b, int off, int len) throws IOException {
+        @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
             synchronized (sharedRaf) {
                 sharedRaf.seek(offset);
-                if (len > length - offset) {
-                    len = (int) (length - offset);
+                if (byteCount > length - offset) {
+                    byteCount = (int) (length - offset);
                 }
-                int count = sharedRaf.read(b, off, len);
+                int count = sharedRaf.read(buffer, byteOffset, byteCount);
                 if (count > 0) {
                     offset += count;
                     return count;
@@ -457,8 +480,8 @@
             this.entry = entry;
         }
 
-        @Override public int read(byte[] buffer, int off, int nbytes) throws IOException {
-            int i = super.read(buffer, off, nbytes);
+        @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+            int i = super.read(buffer, byteOffset, byteCount);
             if (i != -1) {
                 bytesRead += i;
             }
diff --git a/luni/src/main/java/java/util/zip/ZipInputStream.java b/luni/src/main/java/java/util/zip/ZipInputStream.java
index d46e2dd..9c18f49 100644
--- a/luni/src/main/java/java/util/zip/ZipInputStream.java
+++ b/luni/src/main/java/java/util/zip/ZipInputStream.java
@@ -286,15 +286,13 @@
     }
 
     /**
-     * Reads up to the specified number of uncompressed bytes into the buffer
-     * starting at the offset.
-     *
-     * @return the number of bytes read
+     * Reads up to {@code byteCount} uncompressed bytes into the buffer
+     * starting at {@code byteOffset}. Returns the number of bytes actually read, or -1.
      */
     @Override
-    public int read(byte[] buffer, int offset, int byteCount) throws IOException {
+    public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
         checkClosed();
-        Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+        Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
 
         if (inf.finished() || currentEntry == null) {
             return -1;
@@ -317,10 +315,10 @@
             if ((csize - inRead) < toRead) {
                 toRead = csize - inRead;
             }
-            System.arraycopy(buf, lastRead, buffer, offset, toRead);
+            System.arraycopy(buf, lastRead, buffer, byteOffset, toRead);
             lastRead += toRead;
             inRead += toRead;
-            crc.update(buffer, offset, toRead);
+            crc.update(buffer, byteOffset, toRead);
             return toRead;
         }
         if (inf.needsInput()) {
@@ -331,14 +329,14 @@
         }
         int read;
         try {
-            read = inf.inflate(buffer, offset, byteCount);
+            read = inf.inflate(buffer, byteOffset, byteCount);
         } catch (DataFormatException e) {
             throw new ZipException(e.getMessage());
         }
         if (read == 0 && inf.finished()) {
             return -1;
         }
-        crc.update(buffer, offset, read);
+        crc.update(buffer, byteOffset, read);
         return read;
     }
 
diff --git a/luni/src/main/java/java/util/zip/ZipOutputStream.java b/luni/src/main/java/java/util/zip/ZipOutputStream.java
index 59849d3..04de03f 100644
--- a/luni/src/main/java/java/util/zip/ZipOutputStream.java
+++ b/luni/src/main/java/java/util/zip/ZipOutputStream.java
@@ -20,7 +20,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.HashSet;
 import libcore.util.EmptyArray;
@@ -69,7 +69,7 @@
      */
     public static final int STORED = 0;
 
-    private static final int ZIPLocalHeaderVersionNeeded = 20;
+    private static final int ZIP_VERSION_2_0 = 20; // Zip specification version 2.0.
 
     private byte[] commentBytes = EmptyArray.BYTE;
 
@@ -158,8 +158,8 @@
         // http://code.google.com/p/android/issues/detail?id=20214
         flags |= ZipFile.GPBF_UTF8_FLAG;
         writeLong(cDir, CENSIG);
-        writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version created
-        writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version to extract
+        writeShort(cDir, ZIP_VERSION_2_0); // Version this file was made by.
+        writeShort(cDir, ZIP_VERSION_2_0); // Minimum version needed to extract.
         writeShort(cDir, flags);
         writeShort(cDir, currentEntry.getMethod());
         writeShort(cDir, currentEntry.time);
@@ -182,7 +182,7 @@
         String comment = currentEntry.getComment();
         byte[] commentBytes = EmptyArray.BYTE;
         if (comment != null) {
-            commentBytes = comment.getBytes(Charsets.UTF_8);
+            commentBytes = comment.getBytes(StandardCharsets.UTF_8);
         }
         writeShort(cDir, commentBytes.length); // Comment length.
         writeShort(cDir, 0); // Disk Start
@@ -294,7 +294,7 @@
             // TODO: support Zip64.
             throw new ZipException("Too many entries for the zip file format's 16-bit entry count");
         }
-        nameBytes = ze.name.getBytes(Charsets.UTF_8);
+        nameBytes = ze.name.getBytes(StandardCharsets.UTF_8);
         nameLength = nameBytes.length;
         if (nameLength > 0xffff) {
             throw new IllegalArgumentException("Name too long: " + nameLength + " UTF-8 bytes");
@@ -313,7 +313,7 @@
         // modified UTF-8. From Java 7, it sets this flag and uses normal UTF-8.)
         flags |= ZipFile.GPBF_UTF8_FLAG;
         writeLong(out, LOCSIG); // Entry header
-        writeShort(out, ZIPLocalHeaderVersionNeeded); // Extraction version
+        writeShort(out, ZIP_VERSION_2_0); // Minimum version needed to extract.
         writeShort(out, flags);
         writeShort(out, method);
         if (currentEntry.getTime() == -1) {
@@ -344,7 +344,7 @@
     }
 
     /**
-     * Sets the comment associated with the file being written.
+     * Sets the comment associated with the file being written. See {@link ZipFile#getComment}.
      * @throws IllegalArgumentException if the comment is >= 64 Ki UTF-8 bytes.
      */
     public void setComment(String comment) {
@@ -353,7 +353,7 @@
             return;
         }
 
-        byte[] newCommentBytes = comment.getBytes(Charsets.UTF_8);
+        byte[] newCommentBytes = comment.getBytes(StandardCharsets.UTF_8);
         if (newCommentBytes.length > 0xffff) {
             throw new IllegalArgumentException("Comment too long: " + newCommentBytes.length + " bytes");
         }
diff --git a/luni/src/main/java/javax/crypto/AEADBadTagException.java b/luni/src/main/java/javax/crypto/AEADBadTagException.java
new file mode 100644
index 0000000..d5d1b11
--- /dev/null
+++ b/luni/src/main/java/javax/crypto/AEADBadTagException.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 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.
+ */
+
+package javax.crypto;
+
+/**
+ * Thrown by a {@link Cipher} that is using an Authenticated Encryption with
+ * Additional Data (AEAD) mode such as Galois/Counter Mode (GCM) and the tag
+ * failed verification.
+ *
+ * @since 1.7
+ */
+public class AEADBadTagException extends BadPaddingException {
+    private static final long serialVersionUID = -488059093241685509L;
+
+    /**
+     * Constructs an instance of {@code AEADBadTagException}.
+     */
+    public AEADBadTagException() {
+        super();
+    }
+
+    /**
+     * Constructs an instance of {@code AEADBadTagException} with the given
+     * {@code message}.
+     */
+    public AEADBadTagException(String message) {
+        super(message);
+    }
+}
diff --git a/luni/src/main/java/javax/crypto/Cipher.java b/luni/src/main/java/javax/crypto/Cipher.java
index aeb5def..ba40b86 100644
--- a/luni/src/main/java/javax/crypto/Cipher.java
+++ b/luni/src/main/java/javax/crypto/Cipher.java
@@ -875,7 +875,7 @@
      *             if this cipher instance is not initialized for encryption or
      *             decryption.
      * @throws IllegalArgumentException
-     *             if the input is {@code null}, or if {@code inputOffset} and
+     *             if {@code input} is {@code null}, or if {@code inputOffset} and
      *             {@code inputLen} do not specify a valid chunk in the input
      *             buffer.
      */
@@ -1026,6 +1026,99 @@
     }
 
     /**
+     * Continues a multi-part transformation (encryption or decryption) with
+     * Authenticated Additional Data (AAD). AAD may only be added after the
+     * {@code Cipher} is initialized and before any data is passed to the
+     * instance.
+     * <p>
+     * This is only usable with cipher modes that support Authenticated
+     * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
+     *
+     * @param input bytes of AAD to use with the cipher
+     * @throws IllegalStateException
+     *             if this cipher instance is not initialized for encryption or
+     *             decryption.
+     * @throws IllegalArgumentException
+     *             if {@code input} is {@code null}
+     * @throws UnsupportedOperationException if the cipher does not support AEAD
+     * @since 1.7
+     */
+    public final void updateAAD(byte[] input) {
+        if (input == null) {
+            throw new IllegalArgumentException("input == null");
+        }
+        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
+            throw new IllegalStateException();
+        }
+        if (input.length == 0) {
+            return;
+        }
+        spiImpl.engineUpdateAAD(input, 0, input.length);
+    }
+
+    /**
+     * Continues a multi-part transformation (encryption or decryption) with
+     * Authenticated Additional Data (AAD). AAD may only be added after the
+     * {@code Cipher} is initialized and before any data is passed to the
+     * instance.
+     * <p>
+     * This is only usable with cipher modes that support Authenticated
+     * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
+     *
+     * @param input bytes of AAD to use with the cipher
+     * @param inputOffset offset within bytes of additional data to add to cipher
+     * @param inputLen length of bytes of additional data to add to cipher
+     * @throws IllegalStateException
+     *             if this cipher instance is not initialized for encryption or
+     *             decryption.
+     * @throws IllegalArgumentException
+     *             if {@code input} is {@code null}, or if {@code inputOffset} and
+     *             {@code inputLen} do not specify a valid chunk in the input
+     *             buffer.
+     * @throws UnsupportedOperationException if the cipher does not support AEAD
+     * @since 1.7
+     */
+    public final void updateAAD(byte[] input, int inputOffset, int inputLen) {
+        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
+            throw new IllegalStateException();
+        }
+        if (input == null) {
+            throw new IllegalArgumentException("input == null");
+        }
+        checkInputOffsetAndCount(input.length, inputOffset, inputLen);
+        if (input.length == 0) {
+            return;
+        }
+        spiImpl.engineUpdateAAD(input, inputOffset, inputLen);
+    }
+
+    /**
+     * Continues a multi-part transformation (encryption or decryption) with
+     * Authenticated Additional Data (AAD). AAD may only be added after the
+     * {@code Cipher} is initialized and before any data is passed to the
+     * instance.
+     * <p>
+     * This is only usable with cipher modes that support Authenticated
+     * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
+     *
+     * @param input buffer of AAD to be used
+     * @throws IllegalStateException
+     *             if this cipher instance is not initialized for encryption or
+     *             decryption.
+     * @throws UnsupportedOperationException if the cipher does not support AEAD
+     * @since 1.7
+     */
+    public final void updateAAD(ByteBuffer input) {
+        if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
+            throw new IllegalStateException("Cipher is not initialized");
+        }
+        if (input == null) {
+            throw new IllegalArgumentException("input == null");
+        }
+        spiImpl.engineUpdateAAD(input);
+    }
+
+    /**
      * Finishes a multi-part transformation (encryption or decryption).
      * <p>
      * Processes any bytes that may have been buffered in previous {@code
diff --git a/luni/src/main/java/javax/crypto/CipherSpi.java b/luni/src/main/java/javax/crypto/CipherSpi.java
index 1f91ba8..70e06b1 100644
--- a/luni/src/main/java/javax/crypto/CipherSpi.java
+++ b/luni/src/main/java/javax/crypto/CipherSpi.java
@@ -368,6 +368,69 @@
     }
 
     /**
+     * Continues a multi-part transformation (encryption or decryption) with
+     * Authenticated Additional Data (AAD). AAD may only be added after the
+     * {@code Cipher} is initialized and before any data is passed to the
+     * instance.
+     * <p>
+     * This is only usable with cipher modes that support Authenticated
+     * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
+     *
+     * @param input bytes of AAD to use with the cipher
+     * @param inputOffset offset within bytes of additional data to add to cipher
+     * @param inputLen length of bytes of additional data to add to cipher
+     * @throws IllegalStateException
+     *             if this cipher instance is not initialized for encryption or
+     *             decryption.
+     * @throws IllegalArgumentException
+     *             if {@code input} is {@code null}, or if {@code inputOffset} and
+     *             {@code inputLen} do not specify a valid chunk in the input
+     *             buffer.
+     * @throws UnsupportedOperationException if the cipher does not support AEAD
+     * @since 1.7
+     */
+    protected void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
+        throw new UnsupportedOperationException(
+                "This cipher does not support Authenticated Encryption with Additional Data");
+    }
+
+    /**
+     * Continues a multi-part transformation (encryption or decryption). The
+     * {@code input.remaining()} bytes starting at {@code input.position()} are
+     * used for the Additional Authenticated Data (AAD). AAD may only be added
+     * after the {@code Cipher} is initialized and before any data is passed to
+     * the instance.
+     * <p>
+     * This is only usable with cipher modes that support Authenticated
+     * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
+     *
+     * @param input the input buffer to transform.
+     * @since 1.7
+     */
+    protected void engineUpdateAAD(ByteBuffer input) {
+        if (input == null) {
+            throw new NullPointerException("input == null");
+        }
+        int position = input.position();
+        int limit = input.limit();
+        if ((limit - position) <= 0) {
+            return;
+        }
+        byte[] bInput;
+        if (input.hasArray()) {
+            bInput = input.array();
+            int offset = input.arrayOffset();
+            engineUpdateAAD(bInput, offset + position, limit - position);
+            input.position(limit);
+        } else {
+            int len = limit - position;
+            bInput = new byte[len];
+            input.get(bInput);
+            engineUpdateAAD(bInput, 0, len);
+        }
+    }
+
+    /**
      * Finishes a multi-part transformation (encryption or decryption).
      * <p>
      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
diff --git a/luni/src/main/java/javax/crypto/spec/GCMParameterSpec.java b/luni/src/main/java/javax/crypto/spec/GCMParameterSpec.java
new file mode 100644
index 0000000..a781697
--- /dev/null
+++ b/luni/src/main/java/javax/crypto/spec/GCMParameterSpec.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 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.
+ */
+
+package javax.crypto.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+
+/**
+ * Provides a the parameters for an instance of a {@link javax.crypto.Cipher}
+ * using Galois/Counter Mode (GCM). This is an Authenticated Encryption with
+ * Associated Data (AEAD) mode for a cipher which allows you to use the
+ * {@link javax.crypto.Cipher#updateAAD(byte[])} method to provide data that is
+ * transmitted in the clear but authenticated using a cryptographic Message
+ * Authentication Code (MAC).
+ *
+ * @since 1.7
+ */
+public class GCMParameterSpec implements AlgorithmParameterSpec {
+    private final int tagLen;
+
+    private final byte[] iv;
+
+    /**
+     * Creates a new {@code GCMParameterSpec} instance from the specified
+     * Initial Vector (IV) from buffer {@code iv} and a tag length of
+     * {@code tagLen} in bits.
+     *
+     * @throws IllegalArgumentException if the specified {@code iv} is null or
+     *             {@code offset} and {@code byteCount} do not specify a valid
+     *             chunk in the specified buffer.
+     */
+    public GCMParameterSpec(int tagLen, byte[] iv) {
+        if (tagLen < 0) {
+            throw new IllegalArgumentException("tag should be a non-negative integer");
+        }
+        if (iv == null) {
+            throw new IllegalArgumentException("iv == null");
+        }
+        this.tagLen = tagLen;
+        this.iv = iv.clone();
+    }
+
+    /**
+     * Creates a new {@code GCMParameterSpec} instance with the Initial Vector
+     * (IV) of {@code byteCount} bytes from the specified buffer {@code iv}
+     * starting at {@code offset} and a tag length of {@code tagLen} in bits.
+     *
+     * @throws IllegalArgumentException if the specified {@code iv} is null or
+     *             {@code offset} and {@code byteCount} do not specify a valid
+     *             chunk in the specified buffer.
+     * @throws ArrayIndexOutOfBoundsException if {@code offset} or
+     *             {@code byteCount} are negative.
+     */
+    public GCMParameterSpec(int tagLen, byte[] iv, int offset, int byteCount) {
+        if (tagLen < 0) {
+            throw new IllegalArgumentException("tag should be a non-negative integer");
+        }
+        if (iv == null) {
+            throw new IllegalArgumentException("iv == null");
+        }
+        try {
+            Arrays.checkOffsetAndCount(iv.length, offset, byteCount);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            throw new IllegalArgumentException(e);
+        }
+        this.tagLen = tagLen;
+        this.iv = Arrays.copyOfRange(iv, offset, offset + byteCount);
+    }
+
+    /**
+     * Returns the size of the tag in bits.
+     */
+    public int getTLen() {
+        return tagLen;
+    }
+
+    /**
+     * Returns the Initial Vector (IV) used by this parameter spec.
+     */
+    public byte[] getIV() {
+        return iv.clone();
+    }
+}
diff --git a/luni/src/main/java/libcore/icu/CollationElementIteratorICU.java b/luni/src/main/java/libcore/icu/CollationElementIteratorICU.java
index 05caa0b..5779d17 100644
--- a/luni/src/main/java/libcore/icu/CollationElementIteratorICU.java
+++ b/luni/src/main/java/libcore/icu/CollationElementIteratorICU.java
@@ -155,12 +155,12 @@
         return order & TERTIARY_ORDER_MASK_;
     }
 
-    public static CollationElementIteratorICU getInstance(int collatorAddress, String source) {
-        int iteratorAddress = NativeCollation.getCollationElementIterator(collatorAddress, source);
+    public static CollationElementIteratorICU getInstance(long collatorAddress, String source) {
+        long iteratorAddress = NativeCollation.getCollationElementIterator(collatorAddress, source);
         return new CollationElementIteratorICU(iteratorAddress);
     }
 
-    private CollationElementIteratorICU(int address) {
+    private CollationElementIteratorICU(long address) {
         this.address = address;
     }
 
@@ -184,7 +184,7 @@
     /**
      * C collator
      */
-    private int address;
+    private final long address;
 
     /**
      * ICU constant primary order mask for collation elements
diff --git a/luni/src/main/java/libcore/icu/DateIntervalFormat.java b/luni/src/main/java/libcore/icu/DateIntervalFormat.java
new file mode 100644
index 0000000..a3e1e5e
--- /dev/null
+++ b/luni/src/main/java/libcore/icu/DateIntervalFormat.java
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+package libcore.icu;
+
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * Exposes icu4c's DateIntervalFormat.
+ */
+public final class DateIntervalFormat {
+
+  // These are all public API in DateUtils. There are others, but they're either for use with
+  // other methods (like FORMAT_ABBREV_RELATIVE), don't internationalize (like FORMAT_CAP_AMPM),
+  // or have never been implemented anyway (like FORMAT_NO_YEAR).
+  public static final int FORMAT_SHOW_TIME = 0x00001;
+  public static final int FORMAT_SHOW_WEEKDAY = 0x00002;
+  public static final int FORMAT_SHOW_YEAR = 0x00004;
+  public static final int FORMAT_SHOW_DATE = 0x00010;
+  public static final int FORMAT_NO_MONTH_DAY = 0x00020;
+  public static final int FORMAT_12HOUR = 0x00040;
+  public static final int FORMAT_24HOUR = 0x00080;
+  public static final int FORMAT_UTC = 0x02000;
+  public static final int FORMAT_ABBREV_TIME = 0x04000;
+  public static final int FORMAT_ABBREV_WEEKDAY = 0x08000;
+  public static final int FORMAT_ABBREV_MONTH = 0x10000;
+  public static final int FORMAT_NUMERIC_DATE = 0x20000;
+  public static final int FORMAT_ABBREV_ALL = 0x80000;
+
+  // TODO: check whether icu4c's DateIntervalFormat is expensive enough to warrant a native peer.
+  private DateIntervalFormat() {
+  }
+
+  // This is public DateUtils API in frameworks/base.
+  public static String formatDateRange(long startMs, long endMs, int flags, String olsonId) {
+    if ((flags & FORMAT_UTC) != 0) {
+      olsonId = "UTC";
+    }
+    TimeZone tz = (olsonId != null) ? TimeZone.getTimeZone(olsonId) : TimeZone.getDefault();
+    return formatDateRange(Locale.getDefault(), tz, startMs, endMs, flags);
+  }
+
+  // This is our slightly more sensible internal API. (A truly sane replacement would take a
+  // skeleton instead of int flags.)
+  public static String formatDateRange(Locale locale, TimeZone tz, long startMs, long endMs, int flags) {
+    String skeleton = toSkeleton(tz, startMs, endMs, flags);
+    return formatDateInterval(skeleton, locale.toString(), tz.getID(), startMs, endMs);
+  }
+
+  private static String toSkeleton(TimeZone tz, long startMs, long endMs, int flags) {
+    Calendar startCalendar = Calendar.getInstance(tz);
+    startCalendar.setTimeInMillis(startMs);
+
+    Calendar endCalendar;
+    if (startMs == endMs) {
+      endCalendar = startCalendar;
+    } else {
+      endCalendar = Calendar.getInstance(tz);
+      endCalendar.setTimeInMillis(endMs);
+    }
+
+    if ((flags & FORMAT_ABBREV_ALL) != 0) {
+      flags |= FORMAT_ABBREV_MONTH | FORMAT_ABBREV_TIME | FORMAT_ABBREV_WEEKDAY;
+    }
+
+    String monthPart = "MMMM";
+    if ((flags & FORMAT_NUMERIC_DATE) != 0) {
+      monthPart = "M";
+    } else if ((flags & FORMAT_ABBREV_MONTH) != 0) {
+      monthPart = "MMM";
+    }
+
+    String weekPart = "EEEE";
+    if ((flags & FORMAT_ABBREV_WEEKDAY) != 0) {
+      weekPart = "EEE";
+    }
+
+    String timePart = "j"; // "j" means choose 12 or 24 hour based on current locale.
+    if ((flags & FORMAT_24HOUR) != 0) {
+      timePart = "H";
+    } else if ((flags & FORMAT_12HOUR) != 0) {
+      timePart = "h";
+    }
+    if ((flags & FORMAT_ABBREV_TIME) == 0 || !onTheHour(startCalendar) || !onTheHour(endCalendar)) {
+      timePart = timePart + "m";
+    }
+
+    if (fallOnDifferentDates(startCalendar, endCalendar)) {
+      flags |= FORMAT_SHOW_DATE;
+    }
+
+    if (fallInSameMonth(startCalendar, endCalendar) && (flags & FORMAT_NO_MONTH_DAY) != 0) {
+      flags &= (~FORMAT_SHOW_WEEKDAY);
+      flags &= (~FORMAT_SHOW_TIME);
+    }
+
+    if ((flags & (FORMAT_SHOW_DATE | FORMAT_SHOW_TIME | FORMAT_SHOW_WEEKDAY)) == 0) {
+      flags |= FORMAT_SHOW_DATE;
+    }
+
+    StringBuilder builder = new StringBuilder();
+    if ((flags & (FORMAT_SHOW_DATE | FORMAT_NO_MONTH_DAY)) != 0) {
+      if ((flags & FORMAT_SHOW_YEAR) != 0) {
+        builder.append("y");
+      }
+      builder.append(monthPart);
+      if ((flags & FORMAT_NO_MONTH_DAY) == 0) {
+        builder.append("d");
+      }
+    }
+    if ((flags & FORMAT_SHOW_WEEKDAY) != 0) {
+      builder.append(weekPart);
+    }
+    if ((flags & FORMAT_SHOW_TIME) != 0) {
+      builder.append(timePart);
+    }
+    return builder.toString();
+  }
+
+  private static boolean onTheHour(Calendar c) {
+    return c.get(Calendar.MINUTE) == 0 && c.get(Calendar.SECOND) == 0;
+  }
+
+  private static boolean fallOnDifferentDates(Calendar c1, Calendar c2) {
+    return c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR) ||
+        c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH) ||
+        c1.get(Calendar.DAY_OF_MONTH) != c2.get(Calendar.DAY_OF_MONTH);
+  }
+
+  private static boolean fallInSameMonth(Calendar c1, Calendar c2) {
+    return c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH);
+  }
+
+  private static native String formatDateInterval(String skeleton, String localeName, String timeZoneName, long fromDate, long toDate);
+}
diff --git a/luni/src/main/java/libcore/icu/ICU.java b/luni/src/main/java/libcore/icu/ICU.java
index 8e0cd0b..6a72d44 100644
--- a/luni/src/main/java/libcore/icu/ICU.java
+++ b/luni/src/main/java/libcore/icu/ICU.java
@@ -129,6 +129,47 @@
 
     public static native String getBestDateTimePattern(String skeleton, String localeName);
 
+    public static char[] getDateFormatOrder(String pattern) {
+      char[] result = new char[3];
+      int resultIndex = 0;
+      boolean sawDay = false;
+      boolean sawMonth = false;
+      boolean sawYear = false;
+
+      for (int i = 0; i < pattern.length(); ++i) {
+        char ch = pattern.charAt(i);
+        if (ch == 'd' || ch == 'L' || ch == 'M' || ch == 'y') {
+          if (ch == 'd' && !sawDay) {
+            result[resultIndex++] = 'd';
+            sawDay = true;
+          } else if ((ch == 'L' || ch == 'M') && !sawMonth) {
+            result[resultIndex++] = 'M';
+            sawMonth = true;
+          } else if ((ch == 'y') && !sawYear) {
+            result[resultIndex++] = 'y';
+            sawYear = true;
+          }
+        } else if (ch == 'G') {
+          // Ignore the era specifier, if present.
+        } else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
+          throw new IllegalArgumentException("Bad pattern character '" + ch + "' in " + pattern);
+        } else if (ch == '\'') {
+          if (i < pattern.length() - 1 && pattern.charAt(i + 1) == '\'') {
+            ++i;
+          } else {
+            i = pattern.indexOf('\'', i + 1);
+            if (i == -1) {
+              throw new IllegalArgumentException("Bad quoting in " + pattern);
+            }
+            ++i;
+          }
+        } else {
+          // Ignore spaces and punctuation.
+        }
+      }
+      return result;
+    }
+
     /**
      * Returns the version of the CLDR data in use, such as "22.1.1".
      */
diff --git a/luni/src/main/java/libcore/icu/LocaleData.java b/luni/src/main/java/libcore/icu/LocaleData.java
index 7a8607b..a6d700f 100644
--- a/luni/src/main/java/libcore/icu/LocaleData.java
+++ b/luni/src/main/java/libcore/icu/LocaleData.java
@@ -79,6 +79,10 @@
     public String mediumDateFormat;
     public String shortDateFormat;
 
+    // shortDateFormat, but guaranteed to have 4-digit years.
+    // Used by android.text.format.DateFormat.getDateFormatStringForSetting.
+    public String shortDateFormat4;
+
     // Used by android.text.format.DateFormat.getTimeFormat.
     public String timeFormat12; // "hh:mm a"
     public String timeFormat24; // "HH:mm"
@@ -187,6 +191,7 @@
             // accidentally eat too much.
             localeData.integerPattern = localeData.numberPattern.replaceAll("\\.[#,]*", "");
         }
+        localeData.shortDateFormat4 = localeData.shortDateFormat.replaceAll("\\byy\\b", "y");
         return localeData;
     }
 }
diff --git a/luni/src/main/java/libcore/icu/NativeBreakIterator.java b/luni/src/main/java/libcore/icu/NativeBreakIterator.java
index 4156f9a..7168d96 100644
--- a/luni/src/main/java/libcore/icu/NativeBreakIterator.java
+++ b/luni/src/main/java/libcore/icu/NativeBreakIterator.java
@@ -29,13 +29,13 @@
 
     // The address of the native peer.
     // Uses of this must be manually synchronized to avoid native crashes.
-    private final int address;
+    private final long address;
 
     private final int type;
     private String string;
     private CharacterIterator charIterator;
 
-    private NativeBreakIterator(int address, int type) {
+    private NativeBreakIterator(long address, int type) {
         this.address = address;
         this.type = type;
         this.charIterator = new StringCharacterIterator("");
@@ -43,7 +43,7 @@
 
     @Override
     public Object clone() {
-        int cloneAddr = cloneImpl(this.address);
+        long cloneAddr = cloneImpl(this.address);
         NativeBreakIterator clone = new NativeBreakIterator(cloneAddr, this.type);
         clone.string = this.string;
         // The RI doesn't clone the CharacterIterator.
@@ -157,21 +157,21 @@
         return new NativeBreakIterator(getWordInstanceImpl(where.toString()), BI_WORD_INSTANCE);
     }
 
-    private static native int getCharacterInstanceImpl(String locale);
-    private static native int getWordInstanceImpl(String locale);
-    private static native int getLineInstanceImpl(String locale);
-    private static native int getSentenceInstanceImpl(String locale);
-    private static synchronized native int cloneImpl(int address);
+    private static native long getCharacterInstanceImpl(String locale);
+    private static native long getWordInstanceImpl(String locale);
+    private static native long getLineInstanceImpl(String locale);
+    private static native long getSentenceInstanceImpl(String locale);
+    private static synchronized native long cloneImpl(long address);
 
-    private static synchronized native void closeImpl(int address);
+    private static synchronized native void closeImpl(long address);
 
-    private static synchronized native void setTextImpl(int address, String text);
-    private static synchronized native int precedingImpl(int address, String text, int offset);
-    private static synchronized native boolean isBoundaryImpl(int address, String text, int offset);
-    private static synchronized native int nextImpl(int address, String text, int n);
-    private static synchronized native int previousImpl(int address, String text);
-    private static synchronized native int currentImpl(int address, String text);
-    private static synchronized native int firstImpl(int address, String text);
-    private static synchronized native int followingImpl(int address, String text, int offset);
-    private static synchronized native int lastImpl(int address, String text);
+    private static synchronized native void setTextImpl(long address, String text);
+    private static synchronized native int precedingImpl(long address, String text, int offset);
+    private static synchronized native boolean isBoundaryImpl(long address, String text, int offset);
+    private static synchronized native int nextImpl(long address, String text, int n);
+    private static synchronized native int previousImpl(long address, String text);
+    private static synchronized native int currentImpl(long address, String text);
+    private static synchronized native int firstImpl(long address, String text);
+    private static synchronized native int followingImpl(long address, String text, int offset);
+    private static synchronized native int lastImpl(long address, String text);
 }
diff --git a/luni/src/main/java/libcore/icu/NativeCollation.java b/luni/src/main/java/libcore/icu/NativeCollation.java
index 2f61c49..0373fef 100644
--- a/luni/src/main/java/libcore/icu/NativeCollation.java
+++ b/luni/src/main/java/libcore/icu/NativeCollation.java
@@ -20,24 +20,24 @@
     }
 
     // Collator.
-    public static native void closeCollator(int address);
-    public static native int compare(int address, String source, String target);
-    public static native int getAttribute(int address, int type);
-    public static native int getCollationElementIterator(int address, String source);
-    public static native String getRules(int address);
-    public static native byte[] getSortKey(int address, String source);
-    public static native int openCollator(String locale);
-    public static native int openCollatorFromRules(String rules, int normalizationMode, int collationStrength);
-    public static native int safeClone(int address);
-    public static native void setAttribute(int address, int type, int value);
+    public static native void closeCollator(long address);
+    public static native int compare(long address, String source, String target);
+    public static native int getAttribute(long address, int type);
+    public static native int 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 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);
 
     // CollationElementIterator.
-    public static native void closeElements(int address);
-    public static native int getMaxExpansion(int address, int order);
-    public static native int getOffset(int address);
-    public static native int next(int address);
-    public static native int previous(int address);
-    public static native void reset(int address);
-    public static native void setOffset(int address, int offset);
-    public static native void setText(int address, String source);
+    public static native void closeElements(long address);
+    public static native int getMaxExpansion(long address, int order);
+    public static native int getOffset(long address);
+    public static native int next(long address);
+    public static native int previous(long address);
+    public static native void reset(long address);
+    public static native void setOffset(long address, int offset);
+    public static native void setText(long address, String source);
 }
diff --git a/luni/src/main/java/libcore/icu/NativeConverter.java b/luni/src/main/java/libcore/icu/NativeConverter.java
index 1b8a7e0..17be458 100644
--- a/luni/src/main/java/libcore/icu/NativeConverter.java
+++ b/luni/src/main/java/libcore/icu/NativeConverter.java
@@ -36,8 +36,6 @@
 
     public static native boolean contains(String converterName1, String converterName2);
 
-    public static native boolean canEncode(long converterHandle, int codeUnit);
-
     public static native String[] getAvailableCharsetNames();
     public static native Charset charsetForName(String charsetName);
 
diff --git a/luni/src/main/java/libcore/icu/NativeDecimalFormat.java b/luni/src/main/java/libcore/icu/NativeDecimalFormat.java
index 376526e..0e9ffc4 100644
--- a/luni/src/main/java/libcore/icu/NativeDecimalFormat.java
+++ b/luni/src/main/java/libcore/icu/NativeDecimalFormat.java
@@ -621,7 +621,7 @@
     }
 
     private static native void applyPatternImpl(long addr, boolean localized, String pattern);
-    private static native int cloneImpl(long addr);
+    private static native long cloneImpl(long addr);
     private static native void close(long addr);
     private static native char[] formatLong(long addr, long value, FieldPositionIterator iter);
     private static native char[] formatDouble(long addr, double value, FieldPositionIterator iter);
diff --git a/luni/src/main/java/libcore/icu/NativePluralRules.java b/luni/src/main/java/libcore/icu/NativePluralRules.java
index 47cc76b..dbcf089 100644
--- a/luni/src/main/java/libcore/icu/NativePluralRules.java
+++ b/luni/src/main/java/libcore/icu/NativePluralRules.java
@@ -32,9 +32,9 @@
     public static final int MANY  = 4;
     public static final int OTHER = 5;
 
-    private final int address;
+    private final long address;
 
-    private NativePluralRules(int address) {
+    private NativePluralRules(long address) {
         this.address = address;
     }
 
@@ -58,7 +58,7 @@
         return quantityForIntImpl(address, value);
     }
 
-    private static native void finalizeImpl(int address);
-    private static native int forLocaleImpl(String localeName);
-    private static native int quantityForIntImpl(int address, int value);
+    private static native void finalizeImpl(long address);
+    private static native long forLocaleImpl(String localeName);
+    private static native int quantityForIntImpl(long address, int value);
 }
diff --git a/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java b/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
index 4221fe6..3ea942d 100644
--- a/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
+++ b/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
@@ -42,7 +42,7 @@
     public static final int STRENGTH = 5;
 
     // The address of the ICU4C native peer.
-    private int address;
+    private final long address;
 
     public RuleBasedCollatorICU(String rules) throws ParseException {
         if (rules == null) {
@@ -55,7 +55,7 @@
         address = NativeCollation.openCollator(locale.toString());
     }
 
-    private RuleBasedCollatorICU(int address) {
+    private RuleBasedCollatorICU(long address) {
         this.address = address;
     }
 
diff --git a/luni/src/main/java/libcore/icu/TimeZoneNames.java b/luni/src/main/java/libcore/icu/TimeZoneNames.java
index 2db0381..5bb54a1 100644
--- a/luni/src/main/java/libcore/icu/TimeZoneNames.java
+++ b/luni/src/main/java/libcore/icu/TimeZoneNames.java
@@ -149,7 +149,7 @@
     public static String[] forLocale(Locale locale) {
         String countryCode = locale.getCountry();
         ArrayList<String> ids = new ArrayList<String>();
-        for (String line : ZoneInfoDB.getZoneTab().split("\n")) {
+        for (String line : ZoneInfoDB.getInstance().getZoneTab().split("\n")) {
             if (line.startsWith(countryCode)) {
                 int olsonIdStart = line.indexOf('\t', 4) + 1;
                 int olsonIdEnd = line.indexOf('\t', olsonIdStart);
diff --git a/luni/src/main/java/libcore/io/Base64.java b/luni/src/main/java/libcore/io/Base64.java
index e4643b5..00b0251 100644
--- a/luni/src/main/java/libcore/io/Base64.java
+++ b/luni/src/main/java/libcore/io/Base64.java
@@ -21,7 +21,7 @@
 
 package libcore.io;
 
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import libcore.util.EmptyArray;
 
 /**
@@ -156,6 +156,6 @@
                 out[index++] = '=';
                 break;
         }
-        return new String(out, 0, index, Charsets.US_ASCII);
+        return new String(out, 0, index, StandardCharsets.US_ASCII);
     }
 }
diff --git a/luni/src/main/java/libcore/io/DiskLruCache.java b/luni/src/main/java/libcore/io/DiskLruCache.java
deleted file mode 100644
index b9cc0a1..0000000
--- a/luni/src/main/java/libcore/io/DiskLruCache.java
+++ /dev/null
@@ -1,860 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.io;
-
-import java.io.BufferedWriter;
-import java.io.Closeable;
-import java.io.EOFException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.charset.Charsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A cache that uses a bounded amount of space on a filesystem. Each cache
- * entry has a string key and a fixed number of values. Values are byte
- * sequences, accessible as streams or files. Each value must be between {@code
- * 0} and {@code Integer.MAX_VALUE} bytes in length.
- *
- * <p>The cache stores its data in a directory on the filesystem. This
- * directory must be exclusive to the cache; the cache may delete or overwrite
- * files from its directory. It is an error for multiple processes to use the
- * same cache directory at the same time.
- *
- * <p>This cache limits the number of bytes that it will store on the
- * filesystem. When the number of stored bytes exceeds the limit, the cache will
- * remove entries in the background until the limit is satisfied. The limit is
- * not strict: the cache may temporarily exceed it while waiting for files to be
- * deleted. The limit does not include filesystem overhead or the cache
- * journal so space-sensitive applications should set a conservative limit.
- *
- * <p>Clients call {@link #edit} to create or update the values of an entry. An
- * entry may have only one editor at one time; if a value is not available to be
- * edited then {@link #edit} will return null.
- * <ul>
- *     <li>When an entry is being <strong>created</strong> it is necessary to
- *         supply a full set of values; the empty value should be used as a
- *         placeholder if necessary.
- *     <li>When an entry is being <strong>edited</strong>, it is not necessary
- *         to supply data for every value; values default to their previous
- *         value.
- * </ul>
- * Every {@link #edit} call must be matched by a call to {@link Editor#commit}
- * or {@link Editor#abort}. Committing is atomic: a read observes the full set
- * of values as they were before or after the commit, but never a mix of values.
- *
- * <p>Clients call {@link #get} to read a snapshot of an entry. The read will
- * observe the value at the time that {@link #get} was called. Updates and
- * removals after the call do not impact ongoing reads.
- *
- * <p>This class is tolerant of some I/O errors. If files are missing from the
- * filesystem, the corresponding entries will be dropped from the cache. If
- * an error occurs while writing a cache value, the edit will fail silently.
- * Callers should handle other problems by catching {@code IOException} and
- * responding appropriately.
- */
-public final class DiskLruCache implements Closeable {
-    static final String JOURNAL_FILE = "journal";
-    static final String JOURNAL_FILE_TMP = "journal.tmp";
-    static final String MAGIC = "libcore.io.DiskLruCache";
-    static final String VERSION_1 = "1";
-    static final long ANY_SEQUENCE_NUMBER = -1;
-    private static final String CLEAN = "CLEAN";
-    private static final String DIRTY = "DIRTY";
-    private static final String REMOVE = "REMOVE";
-    private static final String READ = "READ";
-
-    /*
-     * This cache uses a journal file named "journal". A typical journal file
-     * looks like this:
-     *     libcore.io.DiskLruCache
-     *     1
-     *     100
-     *     2
-     *
-     *     CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054
-     *     DIRTY 335c4c6028171cfddfbaae1a9c313c52
-     *     CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342
-     *     REMOVE 335c4c6028171cfddfbaae1a9c313c52
-     *     DIRTY 1ab96a171faeeee38496d8b330771a7a
-     *     CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234
-     *     READ 335c4c6028171cfddfbaae1a9c313c52
-     *     READ 3400330d1dfc7f3f7f4b8d4d803dfcf6
-     *
-     * The first five lines of the journal form its header. They are the
-     * constant string "libcore.io.DiskLruCache", the disk cache's version,
-     * the application's version, the value count, and a blank line.
-     *
-     * Each of the subsequent lines in the file is a record of the state of a
-     * cache entry. Each line contains space-separated values: a state, a key,
-     * and optional state-specific values.
-     *   o DIRTY lines track that an entry is actively being created or updated.
-     *     Every successful DIRTY action should be followed by a CLEAN or REMOVE
-     *     action. DIRTY lines without a matching CLEAN or REMOVE indicate that
-     *     temporary files may need to be deleted.
-     *   o CLEAN lines track a cache entry that has been successfully published
-     *     and may be read. A publish line is followed by the lengths of each of
-     *     its values.
-     *   o READ lines track accesses for LRU.
-     *   o REMOVE lines track entries that have been deleted.
-     *
-     * The journal file is appended to as cache operations occur. The journal may
-     * occasionally be compacted by dropping redundant lines. A temporary file named
-     * "journal.tmp" will be used during compaction; that file should be deleted if
-     * it exists when the cache is opened.
-     */
-
-    private final File directory;
-    private final File journalFile;
-    private final File journalFileTmp;
-    private final int appVersion;
-    private final long maxSize;
-    private final int valueCount;
-    private long size = 0;
-    private Writer journalWriter;
-    private final LinkedHashMap<String, Entry> lruEntries
-            = new LinkedHashMap<String, Entry>(0, 0.75f, true);
-    private int redundantOpCount;
-
-    /**
-     * To differentiate between old and current snapshots, each entry is given
-     * a sequence number each time an edit is committed. A snapshot is stale if
-     * its sequence number is not equal to its entry's sequence number.
-     */
-    private long nextSequenceNumber = 0;
-
-    /** This cache uses a single background thread to evict entries. */
-    private final ExecutorService executorService = new ThreadPoolExecutor(0, 1,
-            60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
-    private final Callable<Void> cleanupCallable = new Callable<Void>() {
-        @Override public Void call() throws Exception {
-            synchronized (DiskLruCache.this) {
-                if (journalWriter == null) {
-                    return null; // closed
-                }
-                trimToSize();
-                if (journalRebuildRequired()) {
-                    rebuildJournal();
-                    redundantOpCount = 0;
-                }
-            }
-            return null;
-        }
-    };
-
-    private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) {
-        this.directory = directory;
-        this.appVersion = appVersion;
-        this.journalFile = new File(directory, JOURNAL_FILE);
-        this.journalFileTmp = new File(directory, JOURNAL_FILE_TMP);
-        this.valueCount = valueCount;
-        this.maxSize = maxSize;
-    }
-
-    /**
-     * Opens the cache in {@code directory}, creating a cache if none exists
-     * there.
-     *
-     * @param directory a writable directory
-     * @param appVersion
-     * @param valueCount the number of values per cache entry. Must be positive.
-     * @param maxSize the maximum number of bytes this cache should use to store
-     * @throws IOException if reading or writing the cache directory fails
-     */
-    public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
-            throws IOException {
-        if (maxSize <= 0) {
-            throw new IllegalArgumentException("maxSize <= 0");
-        }
-        if (valueCount <= 0) {
-            throw new IllegalArgumentException("valueCount <= 0");
-        }
-
-        // prefer to pick up where we left off
-        DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
-        if (cache.journalFile.exists()) {
-            try {
-                cache.readJournal();
-                cache.processJournal();
-                cache.journalWriter = new BufferedWriter(new FileWriter(cache.journalFile, true));
-                return cache;
-            } catch (IOException journalIsCorrupt) {
-                System.logW("DiskLruCache " + directory + " is corrupt: "
-                        + journalIsCorrupt.getMessage() + ", removing");
-                cache.delete();
-            }
-        }
-
-        // create a new empty cache
-        directory.mkdirs();
-        cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
-        cache.rebuildJournal();
-        return cache;
-    }
-
-    private void readJournal() throws IOException {
-        StrictLineReader reader = new StrictLineReader(new FileInputStream(journalFile),
-                Charsets.US_ASCII);
-        try {
-            String magic = reader.readLine();
-            String version = reader.readLine();
-            String appVersionString = reader.readLine();
-            String valueCountString = reader.readLine();
-            String blank = reader.readLine();
-            if (!MAGIC.equals(magic)
-                    || !VERSION_1.equals(version)
-                    || !Integer.toString(appVersion).equals(appVersionString)
-                    || !Integer.toString(valueCount).equals(valueCountString)
-                    || !"".equals(blank)) {
-                throw new IOException("unexpected journal header: ["
-                        + magic + ", " + version + ", " + valueCountString + ", " + blank + "]");
-            }
-
-            int lineCount = 0;
-            while (true) {
-                try {
-                    readJournalLine(reader.readLine());
-                    lineCount++;
-                } catch (EOFException endOfJournal) {
-                    break;
-                }
-            }
-            redundantOpCount = lineCount - lruEntries.size();
-        } finally {
-            IoUtils.closeQuietly(reader);
-        }
-    }
-
-    private void readJournalLine(String line) throws IOException {
-        int firstSpace = line.indexOf(' ');
-        if (firstSpace == -1) {
-            throw new IOException("unexpected journal line: " + line);
-        }
-
-        int keyBegin = firstSpace + 1;
-        int secondSpace = line.indexOf(' ', keyBegin);
-        final String key;
-        if (secondSpace == -1) {
-            key = line.substring(keyBegin);
-            if (firstSpace == REMOVE.length() && line.startsWith(REMOVE)) {
-                lruEntries.remove(key);
-                return;
-            }
-        } else {
-            key = line.substring(keyBegin, secondSpace);
-        }
-
-        Entry entry = lruEntries.get(key);
-        if (entry == null) {
-            entry = new Entry(key);
-            lruEntries.put(key, entry);
-        }
-
-        if (secondSpace != -1 && firstSpace == CLEAN.length() && line.startsWith(CLEAN)) {
-            String[] parts = line.substring(secondSpace + 1).split(" ");
-            entry.readable = true;
-            entry.currentEditor = null;
-            entry.setLengths(parts);
-        } else if (secondSpace == -1 && firstSpace == DIRTY.length() && line.startsWith(DIRTY)) {
-            entry.currentEditor = new Editor(entry);
-        } else if (secondSpace == -1 && firstSpace == READ.length() && line.startsWith(READ)) {
-            // this work was already done by calling lruEntries.get()
-        } else {
-            throw new IOException("unexpected journal line: " + line);
-        }
-    }
-
-    /**
-     * Computes the initial size and collects garbage as a part of opening the
-     * cache. Dirty entries are assumed to be inconsistent and will be deleted.
-     */
-    private void processJournal() throws IOException {
-        deleteIfExists(journalFileTmp);
-        for (Iterator<Entry> i = lruEntries.values().iterator(); i.hasNext(); ) {
-            Entry entry = i.next();
-            if (entry.currentEditor == null) {
-                for (int t = 0; t < valueCount; t++) {
-                    size += entry.lengths[t];
-                }
-            } else {
-                entry.currentEditor = null;
-                for (int t = 0; t < valueCount; t++) {
-                    deleteIfExists(entry.getCleanFile(t));
-                    deleteIfExists(entry.getDirtyFile(t));
-                }
-                i.remove();
-            }
-        }
-    }
-
-    /**
-     * Creates a new journal that omits redundant information. This replaces the
-     * current journal if it exists.
-     */
-    private synchronized void rebuildJournal() throws IOException {
-        if (journalWriter != null) {
-            journalWriter.close();
-        }
-
-        Writer writer = new BufferedWriter(new FileWriter(journalFileTmp));
-        writer.write(MAGIC);
-        writer.write("\n");
-        writer.write(VERSION_1);
-        writer.write("\n");
-        writer.write(Integer.toString(appVersion));
-        writer.write("\n");
-        writer.write(Integer.toString(valueCount));
-        writer.write("\n");
-        writer.write("\n");
-
-        for (Entry entry : lruEntries.values()) {
-            if (entry.currentEditor != null) {
-                writer.write(DIRTY + ' ' + entry.key + '\n');
-            } else {
-                writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
-            }
-        }
-
-        writer.close();
-        journalFileTmp.renameTo(journalFile);
-        journalWriter = new BufferedWriter(new FileWriter(journalFile, true));
-    }
-
-    private static void deleteIfExists(File file) throws IOException {
-        try {
-            Libcore.os.remove(file.getPath());
-        } catch (ErrnoException errnoException) {
-            if (errnoException.errno != OsConstants.ENOENT) {
-                throw errnoException.rethrowAsIOException();
-            }
-        }
-    }
-
-    /**
-     * Returns a snapshot of the entry named {@code key}, or null if it doesn't
-     * exist is not currently readable. If a value is returned, it is moved to
-     * the head of the LRU queue.
-     */
-    public synchronized Snapshot get(String key) throws IOException {
-        checkNotClosed();
-        validateKey(key);
-        Entry entry = lruEntries.get(key);
-        if (entry == null) {
-            return null;
-        }
-
-        if (!entry.readable) {
-            return null;
-        }
-
-        /*
-         * Open all streams eagerly to guarantee that we see a single published
-         * snapshot. If we opened streams lazily then the streams could come
-         * from different edits.
-         */
-        InputStream[] ins = new InputStream[valueCount];
-        try {
-            for (int i = 0; i < valueCount; i++) {
-                ins[i] = new FileInputStream(entry.getCleanFile(i));
-            }
-        } catch (FileNotFoundException e) {
-            // a file must have been deleted manually!
-            return null;
-        }
-
-        redundantOpCount++;
-        journalWriter.append(READ + ' ' + key + '\n');
-        if (journalRebuildRequired()) {
-            executorService.submit(cleanupCallable);
-        }
-
-        return new Snapshot(key, entry.sequenceNumber, ins);
-    }
-
-    /**
-     * Returns an editor for the entry named {@code key}, or null if another
-     * edit is in progress.
-     */
-    public Editor edit(String key) throws IOException {
-        return edit(key, ANY_SEQUENCE_NUMBER);
-    }
-
-    private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException {
-        checkNotClosed();
-        validateKey(key);
-        Entry entry = lruEntries.get(key);
-        if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER
-                && (entry == null || entry.sequenceNumber != expectedSequenceNumber)) {
-            return null; // snapshot is stale
-        }
-        if (entry == null) {
-            entry = new Entry(key);
-            lruEntries.put(key, entry);
-        } else if (entry.currentEditor != null) {
-            return null; // another edit is in progress
-        }
-
-        Editor editor = new Editor(entry);
-        entry.currentEditor = editor;
-
-        // flush the journal before creating files to prevent file leaks
-        journalWriter.write(DIRTY + ' ' + key + '\n');
-        journalWriter.flush();
-        return editor;
-    }
-
-    /**
-     * Returns the directory where this cache stores its data.
-     */
-    public File getDirectory() {
-        return directory;
-    }
-
-    /**
-     * Returns the maximum number of bytes that this cache should use to store
-     * its data.
-     */
-    public long maxSize() {
-        return maxSize;
-    }
-
-    /**
-     * Returns the number of bytes currently being used to store the values in
-     * this cache. This may be greater than the max size if a background
-     * deletion is pending.
-     */
-    public synchronized long size() {
-        return size;
-    }
-
-    private synchronized void completeEdit(Editor editor, boolean success) throws IOException {
-        Entry entry = editor.entry;
-        if (entry.currentEditor != editor) {
-            throw new IllegalStateException();
-        }
-
-        // if this edit is creating the entry for the first time, every index must have a value
-        if (success && !entry.readable) {
-            for (int i = 0; i < valueCount; i++) {
-                if (!editor.written[i]) {
-                    editor.abort();
-                    throw new IllegalStateException("Newly created entry didn't create value for index " + i);
-                }
-                if (!entry.getDirtyFile(i).exists()) {
-                    editor.abort();
-                    System.logW("DiskLruCache: Newly created entry doesn't have file for index " + i);
-                    return;
-                }
-            }
-        }
-
-        for (int i = 0; i < valueCount; i++) {
-            File dirty = entry.getDirtyFile(i);
-            if (success) {
-                if (dirty.exists()) {
-                    File clean = entry.getCleanFile(i);
-                    dirty.renameTo(clean);
-                    long oldLength = entry.lengths[i];
-                    long newLength = clean.length();
-                    entry.lengths[i] = newLength;
-                    size = size - oldLength + newLength;
-                }
-            } else {
-                deleteIfExists(dirty);
-            }
-        }
-
-        redundantOpCount++;
-        entry.currentEditor = null;
-        if (entry.readable | success) {
-            entry.readable = true;
-            journalWriter.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
-            if (success) {
-                entry.sequenceNumber = nextSequenceNumber++;
-            }
-        } else {
-            lruEntries.remove(entry.key);
-            journalWriter.write(REMOVE + ' ' + entry.key + '\n');
-        }
-
-        if (size > maxSize || journalRebuildRequired()) {
-            executorService.submit(cleanupCallable);
-        }
-    }
-
-    /**
-     * We only rebuild the journal when it will halve the size of the journal
-     * and eliminate at least 2000 ops.
-     */
-    private boolean journalRebuildRequired() {
-        final int REDUNDANT_OP_COMPACT_THRESHOLD = 2000;
-        return redundantOpCount >= REDUNDANT_OP_COMPACT_THRESHOLD
-                && redundantOpCount >= lruEntries.size();
-    }
-
-    /**
-     * Drops the entry for {@code key} if it exists and can be removed. Entries
-     * actively being edited cannot be removed.
-     *
-     * @return true if an entry was removed.
-     */
-    public synchronized boolean remove(String key) throws IOException {
-        checkNotClosed();
-        validateKey(key);
-        Entry entry = lruEntries.get(key);
-        if (entry == null || entry.currentEditor != null) {
-            return false;
-        }
-
-        for (int i = 0; i < valueCount; i++) {
-            File file = entry.getCleanFile(i);
-            if (!file.delete()) {
-                throw new IOException("failed to delete " + file);
-            }
-            size -= entry.lengths[i];
-            entry.lengths[i] = 0;
-        }
-
-        redundantOpCount++;
-        journalWriter.append(REMOVE + ' ' + key + '\n');
-        lruEntries.remove(key);
-
-        if (journalRebuildRequired()) {
-            executorService.submit(cleanupCallable);
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns true if this cache has been closed.
-     */
-    public boolean isClosed() {
-        return journalWriter == null;
-    }
-
-    private void checkNotClosed() {
-        if (journalWriter == null) {
-            throw new IllegalStateException("cache is closed");
-        }
-    }
-
-    /**
-     * Force buffered operations to the filesystem.
-     */
-    public synchronized void flush() throws IOException {
-        checkNotClosed();
-        trimToSize();
-        journalWriter.flush();
-    }
-
-    /**
-     * Closes this cache. Stored values will remain on the filesystem.
-     */
-    public synchronized void close() throws IOException {
-        if (journalWriter == null) {
-            return; // already closed
-        }
-        for (Entry entry : new ArrayList<Entry>(lruEntries.values())) {
-            if (entry.currentEditor != null) {
-                entry.currentEditor.abort();
-            }
-        }
-        trimToSize();
-        journalWriter.close();
-        journalWriter = null;
-    }
-
-    private void trimToSize() throws IOException {
-        while (size > maxSize) {
-            Map.Entry<String, Entry> toEvict = lruEntries.eldest();
-            remove(toEvict.getKey());
-        }
-    }
-
-    /**
-     * Closes the cache and deletes all of its stored values. This will delete
-     * all files in the cache directory including files that weren't created by
-     * the cache.
-     */
-    public void delete() throws IOException {
-        close();
-        IoUtils.deleteContents(directory);
-    }
-
-    private void validateKey(String key) {
-        if (key.contains(" ") || key.contains("\n") || key.contains("\r")) {
-            throw new IllegalArgumentException(
-                    "keys must not contain spaces or newlines: \"" + key + "\"");
-        }
-    }
-
-    private static String inputStreamToString(InputStream in) throws IOException {
-        return Streams.readFully(new InputStreamReader(in, Charsets.UTF_8));
-    }
-
-    /**
-     * A snapshot of the values for an entry.
-     */
-    public final class Snapshot implements Closeable {
-        private final String key;
-        private final long sequenceNumber;
-        private final InputStream[] ins;
-
-        private Snapshot(String key, long sequenceNumber, InputStream[] ins) {
-            this.key = key;
-            this.sequenceNumber = sequenceNumber;
-            this.ins = ins;
-        }
-
-        /**
-         * Returns an editor for this snapshot's entry, or null if either the
-         * entry has changed since this snapshot was created or if another edit
-         * is in progress.
-         */
-        public Editor edit() throws IOException {
-            return DiskLruCache.this.edit(key, sequenceNumber);
-        }
-
-        /**
-         * Returns the unbuffered stream with the value for {@code index}.
-         */
-        public InputStream getInputStream(int index) {
-            return ins[index];
-        }
-
-        /**
-         * Returns the string value for {@code index}.
-         */
-        public String getString(int index) throws IOException {
-            return inputStreamToString(getInputStream(index));
-        }
-
-        @Override public void close() {
-            for (InputStream in : ins) {
-                IoUtils.closeQuietly(in);
-            }
-        }
-    }
-
-    /**
-     * Edits the values for an entry.
-     */
-    public final class Editor {
-        private final Entry entry;
-        private final boolean[] written;
-        private boolean hasErrors;
-
-        private Editor(Entry entry) {
-            this.entry = entry;
-            this.written = (entry.readable) ? null : new boolean[valueCount];
-        }
-
-        /**
-         * Returns an unbuffered input stream to read the last committed value,
-         * or null if no value has been committed.
-         */
-        public InputStream newInputStream(int index) throws IOException {
-            synchronized (DiskLruCache.this) {
-                if (entry.currentEditor != this) {
-                    throw new IllegalStateException();
-                }
-                if (!entry.readable) {
-                    return null;
-                }
-                return new FileInputStream(entry.getCleanFile(index));
-            }
-        }
-
-        /**
-         * Returns the last committed value as a string, or null if no value
-         * has been committed.
-         */
-        public String getString(int index) throws IOException {
-            InputStream in = newInputStream(index);
-            return in != null ? inputStreamToString(in) : null;
-        }
-
-        /**
-         * Returns a new unbuffered output stream to write the value at
-         * {@code index}. If the underlying output stream encounters errors
-         * when writing to the filesystem, this edit will be aborted when
-         * {@link #commit} is called. The returned output stream does not throw
-         * IOExceptions.
-         */
-        public OutputStream newOutputStream(int index) throws IOException {
-            synchronized (DiskLruCache.this) {
-                if (entry.currentEditor != this) {
-                    throw new IllegalStateException();
-                }
-                if (!entry.readable) {
-                    written[index] = true;
-                }
-                return new FaultHidingOutputStream(new FileOutputStream(entry.getDirtyFile(index)));
-            }
-        }
-
-        /**
-         * Sets the value at {@code index} to {@code value}.
-         */
-        public void set(int index, String value) throws IOException {
-            Writer writer = null;
-            try {
-                writer = new OutputStreamWriter(newOutputStream(index), Charsets.UTF_8);
-                writer.write(value);
-            } finally {
-                IoUtils.closeQuietly(writer);
-            }
-        }
-
-        /**
-         * Commits this edit so it is visible to readers.  This releases the
-         * edit lock so another edit may be started on the same key.
-         */
-        public void commit() throws IOException {
-            if (hasErrors) {
-                completeEdit(this, false);
-                remove(entry.key); // the previous entry is stale
-            } else {
-                completeEdit(this, true);
-            }
-        }
-
-        /**
-         * Aborts this edit. This releases the edit lock so another edit may be
-         * started on the same key.
-         */
-        public void abort() throws IOException {
-            completeEdit(this, false);
-        }
-
-        private class FaultHidingOutputStream extends FilterOutputStream {
-            private FaultHidingOutputStream(OutputStream out) {
-                super(out);
-            }
-
-            @Override public void write(int oneByte) {
-                try {
-                    out.write(oneByte);
-                } catch (IOException e) {
-                    hasErrors = true;
-                }
-            }
-
-            @Override public void write(byte[] buffer, int offset, int length) {
-                try {
-                    out.write(buffer, offset, length);
-                } catch (IOException e) {
-                    hasErrors = true;
-                }
-            }
-
-            @Override public void close() {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                    hasErrors = true;
-                }
-            }
-
-            @Override public void flush() {
-                try {
-                    out.flush();
-                } catch (IOException e) {
-                    hasErrors = true;
-                }
-            }
-        }
-    }
-
-    private final class Entry {
-        private final String key;
-
-        /** Lengths of this entry's files. */
-        private final long[] lengths;
-
-        /** True if this entry has ever been published */
-        private boolean readable;
-
-        /** The ongoing edit or null if this entry is not being edited. */
-        private Editor currentEditor;
-
-        /** The sequence number of the most recently committed edit to this entry. */
-        private long sequenceNumber;
-
-        private Entry(String key) {
-            this.key = key;
-            this.lengths = new long[valueCount];
-        }
-
-        public String getLengths() throws IOException {
-            StringBuilder result = new StringBuilder();
-            for (long size : lengths) {
-                result.append(' ').append(size);
-            }
-            return result.toString();
-        }
-
-        /**
-         * Set lengths using decimal numbers like "10123".
-         */
-        private void setLengths(String[] strings) throws IOException {
-            if (strings.length != valueCount) {
-                throw invalidLengths(strings);
-            }
-
-            try {
-                for (int i = 0; i < strings.length; i++) {
-                    lengths[i] = Long.parseLong(strings[i]);
-                }
-            } catch (NumberFormatException e) {
-                throw invalidLengths(strings);
-            }
-        }
-
-        private IOException invalidLengths(String[] strings) throws IOException {
-            throw new IOException("unexpected journal line: " + Arrays.toString(strings));
-        }
-
-        public File getCleanFile(int i) {
-            return new File(directory, key + "." + i);
-        }
-
-        public File getDirtyFile(int i) {
-            return new File(directory, key + "." + i + ".tmp");
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index 2de13ae..3800416 100644
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -54,7 +54,7 @@
     public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException { return os.fcntlFlock(fd, cmd, arg); }
     public void fdatasync(FileDescriptor fd) throws ErrnoException { os.fdatasync(fd); }
     public StructStat fstat(FileDescriptor fd) throws ErrnoException { return os.fstat(fd); }
-    public StructStatFs fstatfs(FileDescriptor fd) throws ErrnoException { return os.fstatfs(fd); }
+    public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException { return os.fstatvfs(fd); }
     public void fsync(FileDescriptor fd) throws ErrnoException { os.fsync(fd); }
     public void ftruncate(FileDescriptor fd, long length) throws ErrnoException { os.ftruncate(fd, length); }
     public String gai_strerror(int error) { return os.gai_strerror(error); }
@@ -76,6 +76,7 @@
     public StructLinger getsockoptLinger(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptLinger(fd, level, option); }
     public StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptTimeval(fd, level, option); }
     public StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptUcred(fd, level, option); }
+    public int gettid() { return os.gettid(); }
     public int getuid() { return os.getuid(); }
     public String if_indextoname(int index) { return os.if_indextoname(index); }
     public InetAddress inet_pton(int family, String address) { return os.inet_pton(family, address); }
@@ -128,7 +129,7 @@
     public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException { return os.socket(domain, type, protocol); }
     public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException { os.socketpair(domain, type, protocol, fd1, fd2); }
     public StructStat stat(String path) throws ErrnoException { return os.stat(path); }
-    public StructStatFs statfs(String path) throws ErrnoException { return os.statfs(path); }
+    public StructStatVfs statvfs(String path) throws ErrnoException { return os.statvfs(path); }
     public String strerror(int errno) { return os.strerror(errno); }
     public String strsignal(int signal) { return os.strsignal(signal); }
     public void symlink(String oldPath, String newPath) throws ErrnoException { os.symlink(oldPath, newPath); }
diff --git a/luni/src/main/java/libcore/io/IoBridge.java b/luni/src/main/java/libcore/io/IoBridge.java
index 089d0f8..28adba1 100644
--- a/luni/src/main/java/libcore/io/IoBridge.java
+++ b/luni/src/main/java/libcore/io/IoBridge.java
@@ -577,23 +577,23 @@
         }
     }
 
-    public static InetAddress getSocketLocalAddress(FileDescriptor fd) {
+    public static InetAddress getSocketLocalAddress(FileDescriptor fd) throws SocketException {
         try {
             SocketAddress sa = Libcore.os.getsockname(fd);
             InetSocketAddress isa = (InetSocketAddress) sa;
             return isa.getAddress();
         } catch (ErrnoException errnoException) {
-            throw new AssertionError(errnoException);
+            throw errnoException.rethrowAsSocketException();
         }
     }
 
-    public static int getSocketLocalPort(FileDescriptor fd) {
+    public static int getSocketLocalPort(FileDescriptor fd) throws SocketException {
         try {
             SocketAddress sa = Libcore.os.getsockname(fd);
             InetSocketAddress isa = (InetSocketAddress) sa;
             return isa.getPort();
         } catch (ErrnoException errnoException) {
-            throw new AssertionError(errnoException);
+            throw errnoException.rethrowAsSocketException();
         }
     }
 }
diff --git a/luni/src/main/java/libcore/io/IoUtils.java b/luni/src/main/java/libcore/io/IoUtils.java
index 24ffd58..f7cc41f 100644
--- a/luni/src/main/java/libcore/io/IoUtils.java
+++ b/luni/src/main/java/libcore/io/IoUtils.java
@@ -22,10 +22,13 @@
 import java.io.InterruptedIOException;
 import java.io.RandomAccessFile;
 import java.net.Socket;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
+import java.util.Random;
 import static libcore.io.OsConstants.*;
 
 public final class IoUtils {
+    private static final Random TEMPORARY_DIRECTORY_PRNG = new Random();
+
     private IoUtils() {
     }
 
@@ -107,7 +110,7 @@
      * Returns the contents of 'path' as a string. The contents are assumed to be UTF-8.
      */
     public static String readFileAsString(String path) throws IOException {
-        return readFileAsBytes(path).toString(Charsets.UTF_8);
+        return readFileAsBytes(path).toString(StandardCharsets.UTF_8);
     }
 
     private static UnsafeByteSequence readFileAsBytes(String path) throws IOException {
@@ -129,28 +132,47 @@
     }
 
     /**
-     * Recursively delete everything in {@code dir}.
+     * Do not use. Use createTemporaryDirectory instead.
+     *
+     * Used by frameworks/base unit tests to clean up a temporary directory.
+     * Deliberately ignores errors, on the assumption that test cleanup is only
+     * supposed to be best-effort.
+     *
+     * @deprecated Use {@link #createTemporaryDirectory} instead.
      */
-    // TODO: this should specify paths as Strings rather than as Files
     public static void deleteContents(File dir) throws IOException {
         File[] files = dir.listFiles();
-        if (files == null) {
-            throw new IOException("listFiles returned null: " + dir);
-        }
-        for (File file : files) {
-            if (file.isDirectory()) {
-                deleteContents(file);
-            }
-            if (!file.delete()) {
-                throw new IOException("failed to delete file: " + file);
+        if (files != null) {
+            for (File file : files) {
+                if (file.isDirectory()) {
+                    deleteContents(file);
+                }
+                file.delete();
             }
         }
     }
 
     /**
+     * Creates a unique new temporary directory under "java.io.tmpdir".
+     */
+    public static File createTemporaryDirectory(String prefix) {
+        while (true) {
+            String candidateName = prefix + TEMPORARY_DIRECTORY_PRNG.nextInt();
+            File result = new File(System.getProperty("java.io.tmpdir"), candidateName);
+            if (result.mkdir()) {
+                return result;
+            }
+        }
+    }
+
+    /**
+     * Do not use. This is for System.loadLibrary use only.
+     *
      * Checks whether {@code path} can be opened read-only. Similar to File.exists, but doesn't
      * require read permission on the parent, so it'll work in more cases, and allow you to
-     * remove read permission from more directories.
+     * remove read permission from more directories. Everyone else should just open(2) and then
+     * use the fd, but the loadLibrary API is broken by its need to ask ClassLoaders where to
+     * find a .so rather than just calling dlopen(3).
      */
     public static boolean canOpenReadOnly(String path) {
         try {
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index f3d2383..2b68027 100644
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -45,7 +45,7 @@
     public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException;
     public void fdatasync(FileDescriptor fd) throws ErrnoException;
     public StructStat fstat(FileDescriptor fd) throws ErrnoException;
-    public StructStatFs fstatfs(FileDescriptor fd) throws ErrnoException;
+    public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException;
     public void fsync(FileDescriptor fd) throws ErrnoException;
     public void ftruncate(FileDescriptor fd, long length) throws ErrnoException;
     public String gai_strerror(int error);
@@ -68,6 +68,7 @@
     public StructLinger getsockoptLinger(FileDescriptor fd, int level, int option) throws ErrnoException;
     public StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException;
     public StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException;
+    public int gettid();
     public int getuid();
     public String if_indextoname(int index);
     public InetAddress inet_pton(int family, String address);
@@ -121,8 +122,7 @@
     public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException;
     public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException;
     public StructStat stat(String path) throws ErrnoException;
-    /* TODO: replace statfs with statvfs. */
-    public StructStatFs statfs(String path) throws ErrnoException;
+    public StructStatVfs statvfs(String path) throws ErrnoException;
     public String strerror(int errno);
     public String strsignal(int signal);
     public void symlink(String oldPath, String newPath) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/OsConstants.java b/luni/src/main/java/libcore/io/OsConstants.java
index bb5c766..edecdd9 100644
--- a/luni/src/main/java/libcore/io/OsConstants.java
+++ b/luni/src/main/java/libcore/io/OsConstants.java
@@ -46,6 +46,43 @@
     public static final int AI_NUMERICSERV = placeholder();
     public static final int AI_PASSIVE = placeholder();
     public static final int AI_V4MAPPED = placeholder();
+    public static final int CAP_AUDIT_CONTROL = placeholder();
+    public static final int CAP_AUDIT_WRITE = placeholder();
+    public static final int CAP_CHOWN = placeholder();
+    public static final int CAP_DAC_OVERRIDE = placeholder();
+    public static final int CAP_DAC_READ_SEARCH = placeholder();
+    public static final int CAP_FOWNER = placeholder();
+    public static final int CAP_FSETID = placeholder();
+    public static final int CAP_IPC_LOCK = placeholder();
+    public static final int CAP_IPC_OWNER = placeholder();
+    public static final int CAP_KILL = placeholder();
+    public static final int CAP_LAST_CAP = placeholder();
+    public static final int CAP_LEASE = placeholder();
+    public static final int CAP_LINUX_IMMUTABLE = placeholder();
+    public static final int CAP_MAC_ADMIN = placeholder();
+    public static final int CAP_MAC_OVERRIDE = placeholder();
+    public static final int CAP_MKNOD = placeholder();
+    public static final int CAP_NET_ADMIN = placeholder();
+    public static final int CAP_NET_BIND_SERVICE = placeholder();
+    public static final int CAP_NET_BROADCAST = placeholder();
+    public static final int CAP_NET_RAW = placeholder();
+    public static final int CAP_SETFCAP = placeholder();
+    public static final int CAP_SETGID = placeholder();
+    public static final int CAP_SETPCAP = placeholder();
+    public static final int CAP_SETUID = placeholder();
+    public static final int CAP_SYS_ADMIN = placeholder();
+    public static final int CAP_SYS_BOOT = placeholder();
+    public static final int CAP_SYS_CHROOT = placeholder();
+    public static final int CAP_SYSLOG = placeholder();
+    public static final int CAP_SYS_MODULE = placeholder();
+    public static final int CAP_SYS_NICE = placeholder();
+    public static final int CAP_SYS_PACCT = placeholder();
+    public static final int CAP_SYS_PTRACE = placeholder();
+    public static final int CAP_SYS_RAWIO = placeholder();
+    public static final int CAP_SYS_RESOURCE = placeholder();
+    public static final int CAP_SYS_TIME = placeholder();
+    public static final int CAP_SYS_TTY_CONFIG = placeholder();
+    public static final int CAP_WAKE_ALARM = placeholder();
     public static final int E2BIG = placeholder();
     public static final int EACCES = placeholder();
     public static final int EADDRINUSE = placeholder();
@@ -174,6 +211,7 @@
     public static final int IFF_SLAVE = placeholder();
     public static final int IFF_UP = placeholder();
     public static final int IPPROTO_ICMP = placeholder();
+    public static final int IPPROTO_ICMPV6 = placeholder();
     public static final int IPPROTO_IP = placeholder();
     public static final int IPPROTO_IPV6 = placeholder();
     public static final int IPPROTO_RAW = placeholder();
diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java
index e9d1da3..b99941c 100644
--- a/luni/src/main/java/libcore/io/Posix.java
+++ b/luni/src/main/java/libcore/io/Posix.java
@@ -48,7 +48,7 @@
     public native int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException;
     public native void fdatasync(FileDescriptor fd) throws ErrnoException;
     public native StructStat fstat(FileDescriptor fd) throws ErrnoException;
-    public native StructStatFs fstatfs(FileDescriptor fd) throws ErrnoException;
+    public native StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException;
     public native void fsync(FileDescriptor fd) throws ErrnoException;
     public native void ftruncate(FileDescriptor fd, long length) throws ErrnoException;
     public native String gai_strerror(int error);
@@ -70,6 +70,7 @@
     public native StructLinger getsockoptLinger(FileDescriptor fd, int level, int option) throws ErrnoException;
     public native StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException;
     public native StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException;
+    public native int gettid();
     public native int getuid();
     public native String if_indextoname(int index);
     public native InetAddress inet_pton(int family, String address);
@@ -172,7 +173,7 @@
     public native FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException;
     public native void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException;
     public native StructStat stat(String path) throws ErrnoException;
-    public native StructStatFs statfs(String path) throws ErrnoException;
+    public native StructStatVfs statvfs(String path) throws ErrnoException;
     public native String strerror(int errno);
     public native String strsignal(int signal);
     public native void symlink(String oldPath, String newPath) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/StrictLineReader.java b/luni/src/main/java/libcore/io/StrictLineReader.java
index 36556a0..a2e55cc 100644
--- a/luni/src/main/java/libcore/io/StrictLineReader.java
+++ b/luni/src/main/java/libcore/io/StrictLineReader.java
@@ -22,7 +22,7 @@
 import java.io.InputStream;
 import java.io.IOException;
 import java.nio.charset.Charset;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 
 /**
  * Buffers input from an {@link InputStream} for reading lines.
@@ -78,7 +78,7 @@
      * @throws IllegalArgumentException for negative or zero {@code capacity}.
      */
     public StrictLineReader(InputStream in, int capacity) {
-        this(in, capacity, Charsets.US_ASCII);
+        this(in, capacity, StandardCharsets.US_ASCII);
     }
 
     /**
@@ -114,8 +114,8 @@
         if (capacity < 0) {
             throw new IllegalArgumentException("capacity <= 0");
         }
-        if (!(charset.equals(Charsets.US_ASCII) || charset.equals(Charsets.UTF_8) ||
-                charset.equals(Charsets.ISO_8859_1))) {
+        if (!(charset.equals(StandardCharsets.US_ASCII) || charset.equals(StandardCharsets.UTF_8) ||
+                charset.equals(StandardCharsets.ISO_8859_1))) {
             throw new IllegalArgumentException("Unsupported encoding");
         }
 
@@ -240,4 +240,3 @@
         end = result;
     }
 }
-
diff --git a/luni/src/main/java/libcore/io/StructStatFs.java b/luni/src/main/java/libcore/io/StructStatFs.java
deleted file mode 100644
index 603dc86..0000000
--- a/luni/src/main/java/libcore/io/StructStatFs.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.io;
-
-/**
- * File information returned by fstatfs(2) and statfs(2).
- *
- * TODO: this should be {@code struct statvfs}, but Bionic doesn't support that yet.
- * @hide until the TODO is fixed.
- */
-public final class StructStatFs {
-    /** File system block size (used for block counts). */
-    public final long f_bsize; /*unsigned long*/
-
-    /** Total block count. */
-    public final long f_blocks; /*fsblkcnt_t*/
-
-    /** Free block count. */
-    public final long f_bfree; /*fsblkcnt_t*/
-
-    /** Free block count available to non-root. */
-    public final long f_bavail; /*fsblkcnt_t*/
-
-    /** Total file (inode) count. */
-    public final long f_files; /*fsfilcnt_t*/
-
-    /** Free file (inode) count. */
-    public final long f_ffree; /*fsfilcnt_t*/
-
-    /** Maximum filename length. */
-    public final long f_namemax; /*unsigned long*/
-
-    /** Fundamental file system block size. */
-    public final long f_frsize; /*unsigned long*/
-
-    StructStatFs(long f_bsize, long f_blocks, long f_bfree, long f_bavail,
-            long f_files, long f_ffree, long f_namemax, long f_frsize) {
-        this.f_bsize = f_bsize;
-        this.f_blocks = f_blocks;
-        this.f_bfree = f_bfree;
-        this.f_bavail = f_bavail;
-        this.f_files = f_files;
-        this.f_ffree = f_ffree;
-        this.f_namemax = f_namemax;
-        this.f_frsize = f_frsize;
-    }
-}
diff --git a/luni/src/main/java/libcore/io/StructStatVfs.java b/luni/src/main/java/libcore/io/StructStatVfs.java
new file mode 100644
index 0000000..bb78ff2
--- /dev/null
+++ b/luni/src/main/java/libcore/io/StructStatVfs.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.io;
+
+/**
+ * File information returned by fstatvfs(2) and statvfs(2).
+ */
+public final class StructStatVfs {
+  /** File system block size (used for block counts). */
+  public final long f_bsize; /*unsigned long*/
+
+  /** Fundamental file system block size. */
+  public final long f_frsize; /*unsigned long*/
+
+  /** Total block count. */
+  public final long f_blocks; /*fsblkcnt_t*/
+
+  /** Free block count. */
+  public final long f_bfree; /*fsblkcnt_t*/
+
+  /** Free block count available to non-root. */
+  public final long f_bavail; /*fsblkcnt_t*/
+
+  /** Total file (inode) count. */
+  public final long f_files; /*fsfilcnt_t*/
+
+  /** Free file (inode) count. */
+  public final long f_ffree; /*fsfilcnt_t*/
+
+  /** Free file (inode) count available to non-root. */
+  public final long f_favail; /*fsfilcnt_t*/
+
+  /** File system id. */
+  public final long f_fsid; /*unsigned long*/
+
+  /** Bit mask of ST_* flags. */
+  public final long f_flag; /*unsigned long*/
+
+  /** Maximum filename length. */
+  public final long f_namemax; /*unsigned long*/
+
+  StructStatVfs(long f_bsize, long f_frsize, long f_blocks, long f_bfree, long f_bavail,
+                long f_files, long f_ffree, long f_favail,
+                long f_fsid, long f_flag, long f_namemax) {
+    this.f_bsize = f_bsize;
+    this.f_frsize = f_frsize;
+    this.f_blocks = f_blocks;
+    this.f_bfree = f_bfree;
+    this.f_bavail = f_bavail;
+    this.f_files = f_files;
+    this.f_ffree = f_ffree;
+    this.f_favail = f_favail;
+    this.f_fsid = f_fsid;
+    this.f_flag = f_flag;
+    this.f_namemax = f_namemax;
+  }
+}
diff --git a/luni/src/main/java/libcore/net/UriCodec.java b/luni/src/main/java/libcore/net/UriCodec.java
index 3db95d0..dd18c5f 100644
--- a/luni/src/main/java/libcore/net/UriCodec.java
+++ b/luni/src/main/java/libcore/net/UriCodec.java
@@ -20,7 +20,7 @@
 import java.io.ByteArrayOutputStream;
 import java.net.URISyntaxException;
 import java.nio.charset.Charset;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 
 /**
  * Encodes and decodes {@code application/x-www-form-urlencoded} content.
@@ -135,11 +135,11 @@
     }
 
     public final void appendEncoded(StringBuilder builder, String s) {
-        appendEncoded(builder, s, Charsets.UTF_8, false);
+        appendEncoded(builder, s, StandardCharsets.UTF_8, false);
     }
 
     public final void appendPartiallyEncoded(StringBuilder builder, String s) {
-        appendEncoded(builder, s, Charsets.UTF_8, true);
+        appendEncoded(builder, s, StandardCharsets.UTF_8, true);
     }
 
     /**
@@ -203,7 +203,7 @@
     }
 
     public static String decode(String s) {
-        return decode(s, false, Charsets.UTF_8, true);
+        return decode(s, false, StandardCharsets.UTF_8, true);
     }
 
     private static void appendHex(StringBuilder builder, String s, Charset charset) {
diff --git a/luni/src/main/java/libcore/net/http/AbstractHttpInputStream.java b/luni/src/main/java/libcore/net/http/AbstractHttpInputStream.java
deleted file mode 100644
index 70f76b7..0000000
--- a/luni/src/main/java/libcore/net/http/AbstractHttpInputStream.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2010 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.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheRequest;
-import libcore.io.Streams;
-
-/**
- * An input stream for the body of an HTTP response.
- *
- * <p>Since a single socket's input stream may be used to read multiple HTTP
- * responses from the same server, subclasses shouldn't close the socket stream.
- *
- * <p>A side effect of reading an HTTP response is that the response cache
- * is populated. If the stream is closed early, that cache entry will be
- * invalidated.
- */
-abstract class AbstractHttpInputStream extends InputStream {
-    protected final InputStream in;
-    protected final HttpEngine httpEngine;
-    private final CacheRequest cacheRequest;
-    private final OutputStream cacheBody;
-    protected boolean closed;
-
-    AbstractHttpInputStream(InputStream in, HttpEngine httpEngine,
-            CacheRequest cacheRequest) throws IOException {
-        this.in = in;
-        this.httpEngine = httpEngine;
-
-        OutputStream cacheBody = cacheRequest != null ? cacheRequest.getBody() : null;
-
-        // some apps return a null body; for compatibility we treat that like a null cache request
-        if (cacheBody == null) {
-            cacheRequest = null;
-        }
-
-        this.cacheBody = cacheBody;
-        this.cacheRequest = cacheRequest;
-    }
-
-    /**
-     * read() is implemented using read(byte[], int, int) so subclasses only
-     * need to override the latter.
-     */
-    @Override public final int read() throws IOException {
-        return Streams.readSingleByte(this);
-    }
-
-    protected final void checkNotClosed() throws IOException {
-        if (closed) {
-            throw new IOException("stream closed");
-        }
-    }
-
-    protected final void cacheWrite(byte[] buffer, int offset, int count) throws IOException {
-        if (cacheBody != null) {
-            cacheBody.write(buffer, offset, count);
-        }
-    }
-
-    /**
-     * Closes the cache entry and makes the socket available for reuse. This
-     * should be invoked when the end of the body has been reached.
-     */
-    protected final void endOfInput(boolean reuseSocket) throws IOException {
-        if (cacheRequest != null) {
-            cacheBody.close();
-        }
-        httpEngine.release(reuseSocket);
-    }
-
-    /**
-     * Calls abort on the cache entry and disconnects the socket. This
-     * should be invoked when the connection is closed unexpectedly to
-     * invalidate the cache entry and to prevent the HTTP connection from
-     * being reused. HTTP messages are sent in serial so whenever a message
-     * cannot be read to completion, subsequent messages cannot be read
-     * either and the connection must be discarded.
-     *
-     * <p>An earlier implementation skipped the remaining bytes, but this
-     * requires that the entire transfer be completed. If the intention was
-     * to cancel the transfer, closing the connection is the only solution.
-     */
-    protected final void unexpectedEndOfInput() {
-        if (cacheRequest != null) {
-            cacheRequest.abort();
-        }
-        httpEngine.release(false);
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/AbstractHttpOutputStream.java b/luni/src/main/java/libcore/net/http/AbstractHttpOutputStream.java
deleted file mode 100644
index 1e1b47b..0000000
--- a/luni/src/main/java/libcore/net/http/AbstractHttpOutputStream.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010 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.net.http;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * An output stream for the body of an HTTP request.
- *
- * <p>Since a single socket's output stream may be used to write multiple HTTP
- * requests to the same server, subclasses should not close the socket stream.
- */
-abstract class AbstractHttpOutputStream extends OutputStream {
-    protected boolean closed;
-
-    @Override public final void write(int data) throws IOException {
-        write(new byte[] { (byte) data });
-    }
-
-    protected final void checkNotClosed() throws IOException {
-        if (closed) {
-            throw new IOException("stream closed");
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/Challenge.java b/luni/src/main/java/libcore/net/http/Challenge.java
deleted file mode 100644
index 0326c17..0000000
--- a/luni/src/main/java/libcore/net/http/Challenge.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-/**
- * An RFC 2617 challenge.
- *
- * @hide
- */
-public final class Challenge {
-    final String scheme;
-    final String realm;
-
-    public Challenge(String scheme, String realm) {
-        this.scheme = scheme;
-        this.realm = realm;
-    }
-
-    @Override public boolean equals(Object o) {
-        return o instanceof Challenge
-                && ((Challenge) o).scheme.equals(scheme)
-                && ((Challenge) o).realm.equals(realm);
-    }
-
-    @Override public int hashCode() {
-        return scheme.hashCode() + 31 * realm.hashCode();
-    }
-
-    @Override public String toString() {
-        return "Challenge[" + scheme + " " + realm + "]";
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/ChunkedInputStream.java b/luni/src/main/java/libcore/net/http/ChunkedInputStream.java
deleted file mode 100644
index 91cff7a..0000000
--- a/luni/src/main/java/libcore/net/http/ChunkedInputStream.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2010 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.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.CacheRequest;
-import java.util.Arrays;
-import libcore.io.Streams;
-
-/**
- * An HTTP body with alternating chunk sizes and chunk bodies.
- */
-final class ChunkedInputStream extends AbstractHttpInputStream {
-    private static final int MIN_LAST_CHUNK_LENGTH = "\r\n0\r\n\r\n".length();
-    private static final int NO_CHUNK_YET = -1;
-    private int bytesRemainingInChunk = NO_CHUNK_YET;
-    private boolean hasMoreChunks = true;
-
-    ChunkedInputStream(InputStream is, CacheRequest cacheRequest,
-            HttpEngine httpEngine) throws IOException {
-        super(is, httpEngine, cacheRequest);
-    }
-
-    @Override public int read(byte[] buffer, int offset, int count) throws IOException {
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-        checkNotClosed();
-
-        if (!hasMoreChunks) {
-            return -1;
-        }
-        if (bytesRemainingInChunk == 0 || bytesRemainingInChunk == NO_CHUNK_YET) {
-            readChunkSize();
-            if (!hasMoreChunks) {
-                return -1;
-            }
-        }
-        int read = in.read(buffer, offset, Math.min(count, bytesRemainingInChunk));
-        if (read == -1) {
-            unexpectedEndOfInput(); // the server didn't supply the promised chunk length
-            throw new IOException("unexpected end of stream");
-        }
-        bytesRemainingInChunk -= read;
-        cacheWrite(buffer, offset, read);
-
-        /*
-         * If we're at the end of a chunk and the next chunk size is readable,
-         * read it! Reading the last chunk causes the underlying connection to
-         * be recycled and we want to do that as early as possible. Otherwise
-         * self-delimiting streams like gzip will never be recycled.
-         * http://code.google.com/p/android/issues/detail?id=7059
-         */
-        if (bytesRemainingInChunk == 0 && in.available() >= MIN_LAST_CHUNK_LENGTH) {
-            readChunkSize();
-        }
-
-        return read;
-    }
-
-    private void readChunkSize() throws IOException {
-        // read the suffix of the previous chunk
-        if (bytesRemainingInChunk != NO_CHUNK_YET) {
-            Streams.readAsciiLine(in);
-        }
-        String chunkSizeString = Streams.readAsciiLine(in);
-        int index = chunkSizeString.indexOf(";");
-        if (index != -1) {
-            chunkSizeString = chunkSizeString.substring(0, index);
-        }
-        try {
-            bytesRemainingInChunk = Integer.parseInt(chunkSizeString.trim(), 16);
-        } catch (NumberFormatException e) {
-            throw new IOException("Expected a hex chunk size, but was " + chunkSizeString);
-        }
-        if (bytesRemainingInChunk == 0) {
-            hasMoreChunks = false;
-            httpEngine.readTrailers();
-            endOfInput(true);
-        }
-    }
-
-    @Override public int available() throws IOException {
-        checkNotClosed();
-        if (!hasMoreChunks || bytesRemainingInChunk == NO_CHUNK_YET) {
-            return 0;
-        }
-        return Math.min(in.available(), bytesRemainingInChunk);
-    }
-
-    @Override public void close() throws IOException {
-        if (closed) {
-            return;
-        }
-
-        closed = true;
-        if (hasMoreChunks) {
-            unexpectedEndOfInput();
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/ChunkedOutputStream.java b/luni/src/main/java/libcore/net/http/ChunkedOutputStream.java
deleted file mode 100644
index db65f7b..0000000
--- a/luni/src/main/java/libcore/net/http/ChunkedOutputStream.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2010 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.net.http;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * An HTTP body with alternating chunk sizes and chunk bodies. Chunks are
- * buffered until {@code maxChunkLength} bytes are ready, at which point the
- * chunk is written and the buffer is cleared.
- */
-final class ChunkedOutputStream extends AbstractHttpOutputStream {
-    private static final byte[] CRLF = { '\r', '\n' };
-    private static final byte[] HEX_DIGITS = {
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
-    };
-    private static final byte[] FINAL_CHUNK = new byte[] { '0', '\r', '\n', '\r', '\n' };
-
-    /** Scratch space for up to 8 hex digits, and then a constant CRLF */
-    private final byte[] hex = { 0, 0, 0, 0, 0, 0, 0, 0, '\r', '\n' };
-
-    private final OutputStream socketOut;
-    private final int maxChunkLength;
-    private final ByteArrayOutputStream bufferedChunk;
-
-
-    public ChunkedOutputStream(OutputStream socketOut, int maxChunkLength) {
-        this.socketOut = socketOut;
-        this.maxChunkLength = Math.max(1, dataLength(maxChunkLength));
-        this.bufferedChunk = new ByteArrayOutputStream(maxChunkLength);
-    }
-
-    /**
-     * Returns the amount of data that can be transmitted in a chunk whose total
-     * length (data+headers) is {@code dataPlusHeaderLength}. This is presumably
-     * useful to match sizes with wire-protocol packets.
-     */
-    private int dataLength(int dataPlusHeaderLength) {
-        int headerLength = 4; // "\r\n" after the size plus another "\r\n" after the data
-        for (int i = dataPlusHeaderLength - headerLength; i > 0; i >>= 4) {
-            headerLength++;
-        }
-        return dataPlusHeaderLength - headerLength;
-    }
-
-    @Override public synchronized void write(byte[] buffer, int offset, int count)
-            throws IOException {
-        checkNotClosed();
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-
-        while (count > 0) {
-            int numBytesWritten;
-
-            if (bufferedChunk.size() > 0 || count < maxChunkLength) {
-                // fill the buffered chunk and then maybe write that to the stream
-                numBytesWritten = Math.min(count, maxChunkLength - bufferedChunk.size());
-                // TODO: skip unnecessary copies from buffer->bufferedChunk?
-                bufferedChunk.write(buffer, offset, numBytesWritten);
-                if (bufferedChunk.size() == maxChunkLength) {
-                    writeBufferedChunkToSocket();
-                }
-
-            } else {
-                // write a single chunk of size maxChunkLength to the stream
-                numBytesWritten = maxChunkLength;
-                writeHex(numBytesWritten);
-                socketOut.write(buffer, offset, numBytesWritten);
-                socketOut.write(CRLF);
-            }
-
-            offset += numBytesWritten;
-            count -= numBytesWritten;
-        }
-    }
-
-    /**
-     * Equivalent to, but cheaper than writing Integer.toHexString().getBytes()
-     * followed by CRLF.
-     */
-    private void writeHex(int i) throws IOException {
-        int cursor = 8;
-        do {
-            hex[--cursor] = HEX_DIGITS[i & 0xf];
-        } while ((i >>>= 4) != 0);
-        socketOut.write(hex, cursor, hex.length - cursor);
-    }
-
-    @Override public synchronized void flush() throws IOException {
-        if (closed) {
-            return; // don't throw; this stream might have been closed on the caller's behalf
-        }
-        writeBufferedChunkToSocket();
-        socketOut.flush();
-    }
-
-    @Override public synchronized void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        closed = true;
-        writeBufferedChunkToSocket();
-        socketOut.write(FINAL_CHUNK);
-    }
-
-    private void writeBufferedChunkToSocket() throws IOException {
-        int size = bufferedChunk.size();
-        if (size <= 0) {
-            return;
-        }
-
-        writeHex(size);
-        bufferedChunk.writeTo(socketOut);
-        bufferedChunk.reset();
-        socketOut.write(CRLF);
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/FixedLengthInputStream.java b/luni/src/main/java/libcore/net/http/FixedLengthInputStream.java
deleted file mode 100644
index 1091af7..0000000
--- a/luni/src/main/java/libcore/net/http/FixedLengthInputStream.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 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.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.CacheRequest;
-import java.util.Arrays;
-
-/**
- * An HTTP body with a fixed length specified in advance.
- */
-final class FixedLengthInputStream extends AbstractHttpInputStream {
-    private int bytesRemaining;
-
-    public FixedLengthInputStream(InputStream is, CacheRequest cacheRequest,
-            HttpEngine httpEngine, int length) throws IOException {
-        super(is, httpEngine, cacheRequest);
-        bytesRemaining = length;
-        if (bytesRemaining == 0) {
-            endOfInput(true);
-        }
-    }
-
-    @Override public int read(byte[] buffer, int offset, int count) throws IOException {
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-        checkNotClosed();
-        if (bytesRemaining == 0) {
-            return -1;
-        }
-        int read = in.read(buffer, offset, Math.min(count, bytesRemaining));
-        if (read == -1) {
-            unexpectedEndOfInput(); // the server didn't supply the promised content length
-            throw new IOException("unexpected end of stream");
-        }
-        bytesRemaining -= read;
-        cacheWrite(buffer, offset, read);
-        if (bytesRemaining == 0) {
-            endOfInput(true);
-        }
-        return read;
-    }
-
-    @Override public int available() throws IOException {
-        checkNotClosed();
-        return bytesRemaining == 0 ? 0 : Math.min(in.available(), bytesRemaining);
-    }
-
-    @Override public void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        closed = true;
-        if (bytesRemaining != 0) {
-            unexpectedEndOfInput();
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/FixedLengthOutputStream.java b/luni/src/main/java/libcore/net/http/FixedLengthOutputStream.java
deleted file mode 100644
index 461eed9..0000000
--- a/luni/src/main/java/libcore/net/http/FixedLengthOutputStream.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2010 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.net.http;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * An HTTP body with a fixed length known in advance.
- */
-final class FixedLengthOutputStream extends AbstractHttpOutputStream {
-    private final OutputStream socketOut;
-    private int bytesRemaining;
-
-    public FixedLengthOutputStream(OutputStream socketOut, int bytesRemaining) {
-        this.socketOut = socketOut;
-        this.bytesRemaining = bytesRemaining;
-    }
-
-    @Override public void write(byte[] buffer, int offset, int count) throws IOException {
-        checkNotClosed();
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-        if (count > bytesRemaining) {
-            throw new IOException("expected " + bytesRemaining + " bytes but received " + count);
-        }
-        socketOut.write(buffer, offset, count);
-        bytesRemaining -= count;
-    }
-
-    @Override public void flush() throws IOException {
-        if (closed) {
-            return; // don't throw; this stream might have been closed on the caller's behalf
-        }
-        socketOut.flush();
-    }
-
-    @Override public void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        closed = true;
-        if (bytesRemaining > 0) {
-            throw new IOException("unexpected end of stream");
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HeaderParser.java b/luni/src/main/java/libcore/net/http/HeaderParser.java
deleted file mode 100644
index 8d5770e..0000000
--- a/luni/src/main/java/libcore/net/http/HeaderParser.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public final class HeaderParser {
-
-    public interface CacheControlHandler {
-        void handle(String directive, String parameter);
-    }
-
-    /**
-     * Parse a comma-separated list of cache control header values.
-     */
-    public static void parseCacheControl(String value, CacheControlHandler handler) {
-        int pos = 0;
-        while (pos < value.length()) {
-            int tokenStart = pos;
-            pos = skipUntil(value, pos, "=,");
-            String directive = value.substring(tokenStart, pos).trim();
-
-            if (pos == value.length() || value.charAt(pos) == ',') {
-                pos++; // consume ',' (if necessary)
-                handler.handle(directive, null);
-                continue;
-            }
-
-            pos++; // consume '='
-            pos = skipWhitespace(value, pos);
-
-            String parameter;
-
-            // quoted string
-            if (pos < value.length() && value.charAt(pos) == '\"') {
-                pos++; // consume '"' open quote
-                int parameterStart = pos;
-                pos = skipUntil(value, pos, "\"");
-                parameter = value.substring(parameterStart, pos);
-                pos++; // consume '"' close quote (if necessary)
-
-            // unquoted string
-            } else {
-                int parameterStart = pos;
-                pos = skipUntil(value, pos, ",");
-                parameter = value.substring(parameterStart, pos).trim();
-            }
-
-            handler.handle(directive, parameter);
-        }
-    }
-
-    /**
-     * Parse RFC 2617 challenges. This API is only interested in the scheme
-     * name and realm.
-     */
-    public static List<Challenge> parseChallenges(
-            RawHeaders responseHeaders, String challengeHeader) {
-        /*
-         * auth-scheme = token
-         * auth-param  = token "=" ( token | quoted-string )
-         * challenge   = auth-scheme 1*SP 1#auth-param
-         * realm       = "realm" "=" realm-value
-         * realm-value = quoted-string
-         */
-        List<Challenge> result = new ArrayList<Challenge>();
-        for (int h = 0; h < responseHeaders.length(); h++) {
-            if (!challengeHeader.equalsIgnoreCase(responseHeaders.getFieldName(h))) {
-                continue;
-            }
-            String value = responseHeaders.getValue(h);
-            int pos = 0;
-            while (pos < value.length()) {
-                int tokenStart = pos;
-                pos = skipUntil(value, pos, " ");
-
-                String scheme = value.substring(tokenStart, pos).trim();
-                pos = skipWhitespace(value, pos);
-
-                // TODO: This currently only handles schemes with a 'realm' parameter;
-                //       It needs to be fixed to handle any scheme and any parameters
-                //       http://code.google.com/p/android/issues/detail?id=11140
-
-                if (!value.regionMatches(pos, "realm=\"", 0, "realm=\"".length())) {
-                    break; // unexpected challenge parameter; give up
-                }
-
-                pos += "realm=\"".length();
-                int realmStart = pos;
-                pos = skipUntil(value, pos, "\"");
-                String realm = value.substring(realmStart, pos);
-                pos++; // consume '"' close quote
-                pos = skipUntil(value, pos, ",");
-                pos++; // consume ',' comma
-                pos = skipWhitespace(value, pos);
-                result.add(new Challenge(scheme, realm));
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Returns the next index in {@code input} at or after {@code pos} that
-     * contains a character from {@code characters}. Returns the input length if
-     * none of the requested characters can be found.
-     */
-    private static int skipUntil(String input, int pos, String characters) {
-        for (; pos < input.length(); pos++) {
-            if (characters.indexOf(input.charAt(pos)) != -1) {
-                break;
-            }
-        }
-        return pos;
-    }
-
-    /**
-     * Returns the next non-whitespace character in {@code input} that is white
-     * space. Result is undefined if input contains newline characters.
-     */
-    private static int skipWhitespace(String input, int pos) {
-        for (; pos < input.length(); pos++) {
-            char c = input.charAt(pos);
-            if (c != ' ' && c != '\t') {
-                break;
-            }
-        }
-        return pos;
-    }
-
-    /**
-     * Returns {@code value} as a positive integer, or 0 if it is negative, or
-     * -1 if it cannot be parsed.
-     */
-    public static int parseSeconds(String value) {
-        try {
-            long seconds = Long.parseLong(value);
-            if (seconds > Integer.MAX_VALUE) {
-                return Integer.MAX_VALUE;
-            } else if (seconds < 0) {
-                return 0;
-            } else {
-                return (int) seconds;
-            }
-        } catch (NumberFormatException e) {
-            return -1;
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpConnection.java b/luni/src/main/java/libcore/net/http/HttpConnection.java
deleted file mode 100644
index 4a6e65d..0000000
--- a/luni/src/main/java/libcore/net/http/HttpConnection.java
+++ /dev/null
@@ -1,343 +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 libcore.net.http;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.net.ProxySelector;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.util.List;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import libcore.io.IoUtils;
-import libcore.util.Objects;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
-
-/**
- * Holds the sockets and streams of an HTTP or HTTPS connection, which may be
- * used for multiple HTTP request/response exchanges. Connections may be direct
- * to the origin server or via a proxy. Create an instance using the {@link
- * Address} inner class.
- *
- * <p>Do not confuse this class with the misnamed {@code HttpURLConnection},
- * which isn't so much a connection as a single request/response pair.
- */
-final class HttpConnection {
-    private final Address address;
-    private final Socket socket;
-    private InputStream inputStream;
-    private OutputStream outputStream;
-    private SSLSocket unverifiedSocket;
-    private SSLSocket sslSocket;
-    private InputStream sslInputStream;
-    private OutputStream sslOutputStream;
-    private boolean recycled = false;
-
-    private HttpConnection(Address config, int connectTimeout) throws IOException {
-        this.address = config;
-
-        /*
-         * Try each of the host's addresses for best behavior in mixed IPv4/IPv6
-         * environments. See http://b/2876927
-         * TODO: add a hidden method so that Socket.tryAllAddresses can does this for us
-         */
-        Socket socketCandidate = null;
-        InetAddress[] addresses = InetAddress.getAllByName(config.socketHost);
-        for (int i = 0; i < addresses.length; i++) {
-            socketCandidate = (config.proxy != null && config.proxy.type() != Proxy.Type.HTTP)
-                    ? new Socket(config.proxy)
-                    : new Socket();
-            try {
-                socketCandidate.connect(
-                        new InetSocketAddress(addresses[i], config.socketPort), connectTimeout);
-                break;
-            } catch (IOException e) {
-                if (i == addresses.length - 1) {
-                    throw e;
-                }
-            }
-        }
-
-        this.socket = socketCandidate;
-    }
-
-    public static HttpConnection connect(URI uri, SSLSocketFactory sslSocketFactory,
-            Proxy proxy, boolean requiresTunnel, int connectTimeout) throws IOException {
-        /*
-         * Try an explicitly-specified proxy.
-         */
-        if (proxy != null) {
-            Address address = (proxy.type() == Proxy.Type.DIRECT)
-                    ? new Address(uri, sslSocketFactory)
-                    : new Address(uri, sslSocketFactory, proxy, requiresTunnel);
-            return HttpConnectionPool.INSTANCE.get(address, connectTimeout);
-        }
-
-        /*
-         * Try connecting to each of the proxies provided by the ProxySelector
-         * until a connection succeeds.
-         */
-        ProxySelector selector = ProxySelector.getDefault();
-        List<Proxy> proxyList = selector.select(uri);
-        if (proxyList != null) {
-            for (Proxy selectedProxy : proxyList) {
-                if (selectedProxy.type() == Proxy.Type.DIRECT) {
-                    // the same as NO_PROXY
-                    // TODO: if the selector recommends a direct connection, attempt that?
-                    continue;
-                }
-                try {
-                    Address address = new Address(uri, sslSocketFactory,
-                            selectedProxy, requiresTunnel);
-                    return HttpConnectionPool.INSTANCE.get(address, connectTimeout);
-                } catch (IOException e) {
-                    // failed to connect, tell it to the selector
-                    selector.connectFailed(uri, selectedProxy.address(), e);
-                }
-            }
-        }
-
-        /*
-         * Try a direct connection. If this fails, this method will throw.
-         */
-        return HttpConnectionPool.INSTANCE.get(new Address(uri, sslSocketFactory), connectTimeout);
-    }
-
-    public void closeSocketAndStreams() {
-        IoUtils.closeQuietly(sslOutputStream);
-        IoUtils.closeQuietly(sslInputStream);
-        IoUtils.closeQuietly(sslSocket);
-        IoUtils.closeQuietly(outputStream);
-        IoUtils.closeQuietly(inputStream);
-        IoUtils.closeQuietly(socket);
-    }
-
-    public void setSoTimeout(int readTimeout) throws SocketException {
-        socket.setSoTimeout(readTimeout);
-    }
-
-    public OutputStream getOutputStream() throws IOException {
-        if (sslSocket != null) {
-            if (sslOutputStream == null) {
-                sslOutputStream = sslSocket.getOutputStream();
-            }
-            return sslOutputStream;
-        } else if(outputStream == null) {
-            outputStream = socket.getOutputStream();
-        }
-        return outputStream;
-    }
-
-    public InputStream getInputStream() throws IOException {
-        if (sslSocket != null) {
-            if (sslInputStream == null) {
-                sslInputStream = sslSocket.getInputStream();
-            }
-            return sslInputStream;
-        } else if (inputStream == null) {
-            /*
-             * Buffer the socket stream to permit efficient parsing of HTTP
-             * headers and chunk sizes. Benchmarks suggest 128 is sufficient.
-             * We cannot buffer when setting up a tunnel because we may consume
-             * bytes intended for the SSL socket.
-             */
-            int bufferSize = 128;
-            inputStream = address.requiresTunnel
-                    ? socket.getInputStream()
-                    : new BufferedInputStream(socket.getInputStream(), bufferSize);
-        }
-        return inputStream;
-    }
-
-    protected Socket getSocket() {
-        return sslSocket != null ? sslSocket : socket;
-    }
-
-    public Address getAddress() {
-        return address;
-    }
-
-    /**
-     * Create an {@code SSLSocket} and perform the SSL handshake
-     * (performing certificate validation.
-     *
-     * @param sslSocketFactory Source of new {@code SSLSocket} instances.
-     * @param tlsTolerant If true, assume server can handle common
-     * TLS extensions and SSL deflate compression. If false, use
-     * an SSL3 only fallback mode without compression.
-     */
-    public void setupSecureSocket(SSLSocketFactory sslSocketFactory, boolean tlsTolerant)
-            throws IOException {
-        // create the wrapper over connected socket
-        unverifiedSocket = (SSLSocket) sslSocketFactory.createSocket(socket,
-                address.uriHost, address.uriPort, true /* autoClose */);
-        // tlsTolerant mimics Chrome's behavior
-        if (tlsTolerant && unverifiedSocket instanceof OpenSSLSocketImpl) {
-            OpenSSLSocketImpl openSslSocket = (OpenSSLSocketImpl) unverifiedSocket;
-            openSslSocket.setUseSessionTickets(true);
-            openSslSocket.setHostname(address.uriHost);
-            // use SSLSocketFactory default enabled protocols
-        } else {
-            unverifiedSocket.setEnabledProtocols(new String [] { "SSLv3" });
-        }
-        // force handshake, which can throw
-        unverifiedSocket.startHandshake();
-    }
-
-    /**
-     * Return an {@code SSLSocket} that is not only connected but has
-     * also passed hostname verification.
-     *
-     * @param hostnameVerifier Used to verify the hostname we
-     * connected to is an acceptable match for the peer certificate
-     * chain of the SSLSession.
-     */
-    public SSLSocket verifySecureSocketHostname(HostnameVerifier hostnameVerifier)
-            throws IOException {
-        if (!hostnameVerifier.verify(address.uriHost, unverifiedSocket.getSession())) {
-            throw new IOException("Hostname '" + address.uriHost + "' was not verified");
-        }
-        sslSocket = unverifiedSocket;
-        return sslSocket;
-    }
-
-    /**
-     * Return an {@code SSLSocket} if already connected, otherwise null.
-     */
-    public SSLSocket getSecureSocketIfConnected() {
-        return sslSocket;
-    }
-
-    /**
-     * Returns true if this connection has been used to satisfy an earlier
-     * HTTP request/response pair.
-     */
-    public boolean isRecycled() {
-        return recycled;
-    }
-
-    public void setRecycled() {
-        this.recycled = true;
-    }
-
-    /**
-     * Returns true if this connection is eligible to be reused for another
-     * request/response pair.
-     */
-    protected boolean isEligibleForRecycling() {
-        return !socket.isClosed()
-                && !socket.isInputShutdown()
-                && !socket.isOutputShutdown();
-    }
-
-    /**
-     * This address has two parts: the address we connect to directly and the
-     * origin address of the resource. These are the same unless a proxy is
-     * being used. It also includes the SSL socket factory so that a socket will
-     * not be reused if its SSL configuration is different.
-     */
-    public static final class Address {
-        private final Proxy proxy;
-        private final boolean requiresTunnel;
-        private final String uriHost;
-        private final int uriPort;
-        private final String socketHost;
-        private final int socketPort;
-        private final SSLSocketFactory sslSocketFactory;
-
-        public Address(URI uri, SSLSocketFactory sslSocketFactory) throws UnknownHostException {
-            this.proxy = null;
-            this.requiresTunnel = false;
-            this.uriHost = uri.getHost();
-            this.uriPort = uri.getEffectivePort();
-            this.sslSocketFactory = sslSocketFactory;
-            this.socketHost = uriHost;
-            this.socketPort = uriPort;
-            if (uriHost == null) {
-                throw new UnknownHostException(uri.toString());
-            }
-        }
-
-        /**
-         * @param requiresTunnel true if the HTTP connection needs to tunnel one
-         *     protocol over another, such as when using HTTPS through an HTTP
-         *     proxy. When doing so, we must avoid buffering bytes intended for
-         *     the higher-level protocol.
-         */
-        public Address(URI uri, SSLSocketFactory sslSocketFactory,
-                Proxy proxy, boolean requiresTunnel) throws UnknownHostException {
-            this.proxy = proxy;
-            this.requiresTunnel = requiresTunnel;
-            this.uriHost = uri.getHost();
-            this.uriPort = uri.getEffectivePort();
-            this.sslSocketFactory = sslSocketFactory;
-
-            SocketAddress proxyAddress = proxy.address();
-            if (!(proxyAddress instanceof InetSocketAddress)) {
-                throw new IllegalArgumentException("Proxy.address() is not an InetSocketAddress: "
-                        + proxyAddress.getClass());
-            }
-            InetSocketAddress proxySocketAddress = (InetSocketAddress) proxyAddress;
-            this.socketHost = proxySocketAddress.getHostName();
-            this.socketPort = proxySocketAddress.getPort();
-            if (uriHost == null) {
-                throw new UnknownHostException(uri.toString());
-            }
-        }
-
-        public Proxy getProxy() {
-            return proxy;
-        }
-
-        @Override public boolean equals(Object other) {
-            if (other instanceof Address) {
-                Address that = (Address) other;
-                return Objects.equal(this.proxy, that.proxy)
-                        && this.uriHost.equals(that.uriHost)
-                        && this.uriPort == that.uriPort
-                        && Objects.equal(this.sslSocketFactory, that.sslSocketFactory)
-                        && this.requiresTunnel == that.requiresTunnel;
-            }
-            return false;
-        }
-
-        @Override public int hashCode() {
-            int result = 17;
-            result = 31 * result + uriHost.hashCode();
-            result = 31 * result + uriPort;
-            result = 31 * result + (sslSocketFactory != null ? sslSocketFactory.hashCode() : 0);
-            result = 31 * result + (proxy != null ? proxy.hashCode() : 0);
-            result = 31 * result + (requiresTunnel ? 1 : 0);
-            return result;
-        }
-
-        public HttpConnection connect(int connectTimeout) throws IOException {
-            return new HttpConnection(this, connectTimeout);
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpConnectionPool.java b/luni/src/main/java/libcore/net/http/HttpConnectionPool.java
deleted file mode 100644
index 1f5f4d9..0000000
--- a/luni/src/main/java/libcore/net/http/HttpConnectionPool.java
+++ /dev/null
@@ -1,120 +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 libcore.net.http;
-
-import dalvik.system.SocketTagger;
-import java.io.IOException;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * A pool of HTTP connections. This class exposes its tuning parameters as
- * system properties:
- * <ul>
- *   <li>{@code http.keepAlive} true if HTTP connections should be pooled at
- *       all. Default is true.
- *   <li>{@code http.maxConnections} maximum number of connections to each URI.
- *       Default is 5.
- * </ul>
- *
- * <p>This class <i>doesn't</i> adjust its configuration as system properties
- * are changed. This assumes that the applications that set these parameters do
- * so before making HTTP connections, and that this class is initialized lazily.
- */
-final class HttpConnectionPool {
-
-    public static final HttpConnectionPool INSTANCE = new HttpConnectionPool();
-
-    private final int maxConnections;
-    private final HashMap<HttpConnection.Address, List<HttpConnection>> connectionPool
-            = new HashMap<HttpConnection.Address, List<HttpConnection>>();
-
-    private HttpConnectionPool() {
-        String keepAlive = System.getProperty("http.keepAlive");
-        if (keepAlive != null && !Boolean.parseBoolean(keepAlive)) {
-            maxConnections = 0;
-            return;
-        }
-
-        String maxConnectionsString = System.getProperty("http.maxConnections");
-        this.maxConnections = maxConnectionsString != null
-                ? Integer.parseInt(maxConnectionsString)
-                : 5;
-    }
-
-    public HttpConnection get(HttpConnection.Address address, int connectTimeout)
-            throws IOException {
-        // First try to reuse an existing HTTP connection.
-        synchronized (connectionPool) {
-            List<HttpConnection> connections = connectionPool.get(address);
-            while (connections != null) {
-                HttpConnection connection = connections.remove(connections.size() - 1);
-                if (connections.isEmpty()) {
-                    connectionPool.remove(address);
-                    connections = null;
-                }
-                if (connection.isEligibleForRecycling()) {
-                    // Since Socket is recycled, re-tag before using
-                    Socket socket = connection.getSocket();
-                    SocketTagger.get().tag(socket);
-                    return connection;
-                }
-            }
-        }
-
-        /*
-         * We couldn't find a reusable connection, so we need to create a new
-         * connection. We're careful not to do so while holding a lock!
-         */
-        return address.connect(connectTimeout);
-    }
-
-    public void recycle(HttpConnection connection) {
-        Socket socket = connection.getSocket();
-        try {
-            SocketTagger.get().untag(socket);
-        } catch (SocketException e) {
-            // When unable to remove tagging, skip recycling and close
-            System.logW("Unable to untagSocket(): " + e);
-            connection.closeSocketAndStreams();
-            return;
-        }
-
-        if (maxConnections > 0 && connection.isEligibleForRecycling()) {
-            HttpConnection.Address address = connection.getAddress();
-            synchronized (connectionPool) {
-                List<HttpConnection> connections = connectionPool.get(address);
-                if (connections == null) {
-                    connections = new ArrayList<HttpConnection>();
-                    connectionPool.put(address, connections);
-                }
-                if (connections.size() < maxConnections) {
-                    connection.setRecycled();
-                    connections.add(connection);
-                    return; // keep the connection open
-                }
-            }
-        }
-
-        // don't close streams while holding a lock!
-        connection.closeSocketAndStreams();
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpEngine.java b/luni/src/main/java/libcore/net/http/HttpEngine.java
deleted file mode 100644
index 8d81c38..0000000
--- a/luni/src/main/java/libcore/net/http/HttpEngine.java
+++ /dev/null
@@ -1,852 +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 libcore.net.http;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.CookieHandler;
-import java.net.ExtendedResponseCache;
-import java.net.HttpURLConnection;
-import java.net.Proxy;
-import java.net.ResponseCache;
-import java.net.ResponseSource;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.charset.Charsets;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.zip.GZIPInputStream;
-import javax.net.ssl.SSLSocketFactory;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-import libcore.util.EmptyArray;
-
-/**
- * Handles a single HTTP request/response pair. Each HTTP engine follows this
- * lifecycle:
- * <ol>
- *     <li>It is created.
- *     <li>The HTTP request message is sent with sendRequest(). Once the request
- *         is sent it is an error to modify the request headers. After
- *         sendRequest() has been called the request body can be written to if
- *         it exists.
- *     <li>The HTTP response message is read with readResponse(). After the
- *         response has been read the response headers and body can be read.
- *         All responses have a response body input stream, though in some
- *         instances this stream is empty.
- * </ol>
- *
- * <p>The request and response may be served by the HTTP response cache, by the
- * network, or by both in the event of a conditional GET.
- *
- * <p>This class may hold a socket connection that needs to be released or
- * recycled. By default, this socket connection is held when the last byte of
- * the response is consumed. To release the connection when it is no longer
- * required, use {@link #automaticallyReleaseConnectionToPool()}.
- */
-public class HttpEngine {
-    private static final CacheResponse GATEWAY_TIMEOUT_RESPONSE = new CacheResponse() {
-        @Override public Map<String, List<String>> getHeaders() throws IOException {
-            Map<String, List<String>> result = new HashMap<String, List<String>>();
-            result.put(null, Collections.singletonList("HTTP/1.1 504 Gateway Timeout"));
-            return result;
-        }
-        @Override public InputStream getBody() throws IOException {
-            return new ByteArrayInputStream(EmptyArray.BYTE);
-        }
-    };
-
-    /**
-     * The maximum number of bytes to buffer when sending headers and a request
-     * body. When the headers and body can be sent in a single write, the
-     * request completes sooner. In one WiFi benchmark, using a large enough
-     * buffer sped up some uploads by half.
-     */
-    private static final int MAX_REQUEST_BUFFER_LENGTH = 32768;
-
-    public static final int DEFAULT_CHUNK_LENGTH = 1024;
-
-    public static final String OPTIONS = "OPTIONS";
-    public static final String GET = "GET";
-    public static final String HEAD = "HEAD";
-    public static final String POST = "POST";
-    public static final String PUT = "PUT";
-    public static final String DELETE = "DELETE";
-    public static final String TRACE = "TRACE";
-    public static final String CONNECT = "CONNECT";
-
-    public static final int HTTP_CONTINUE = 100;
-
-    /**
-     * HTTP 1.1 doesn't specify how many redirects to follow, but HTTP/1.0
-     * recommended 5. http://www.w3.org/Protocols/HTTP/1.0/spec.html#Code3xx
-     */
-    public static final int MAX_REDIRECTS = 5;
-
-    protected final HttpURLConnectionImpl policy;
-
-    protected final String method;
-
-    private ResponseSource responseSource;
-
-    protected HttpConnection connection;
-    private InputStream socketIn;
-    private OutputStream socketOut;
-
-    /**
-     * This stream buffers the request headers and the request body when their
-     * combined size is less than MAX_REQUEST_BUFFER_LENGTH. By combining them
-     * we can save socket writes, which in turn saves a packet transmission.
-     * This is socketOut if the request size is large or unknown.
-     */
-    private OutputStream requestOut;
-    private AbstractHttpOutputStream requestBodyOut;
-
-    private InputStream responseBodyIn;
-
-    private final ResponseCache responseCache = ResponseCache.getDefault();
-    private CacheResponse cacheResponse;
-    private CacheRequest cacheRequest;
-
-    /** The time when the request headers were written, or -1 if they haven't been written yet. */
-    private long sentRequestMillis = -1;
-
-    /**
-     * True if this client added an "Accept-Encoding: gzip" header field and is
-     * therefore responsible for also decompressing the transfer stream.
-     */
-    private boolean transparentGzip;
-
-    boolean sendChunked;
-
-    /**
-     * The version this client will use. Either 0 for HTTP/1.0, or 1 for
-     * HTTP/1.1. Upon receiving a non-HTTP/1.1 response, this client
-     * automatically sets its version to HTTP/1.0.
-     */
-    // TODO: is HTTP minor version tracked across HttpEngines?
-    private int httpMinorVersion = 1; // Assume HTTP/1.1
-
-    private final URI uri;
-
-    private final RequestHeaders requestHeaders;
-
-    /** Null until a response is received from the network or the cache */
-    private ResponseHeaders responseHeaders;
-
-    /*
-     * The cache response currently being validated on a conditional get. Null
-     * if the cached response doesn't exist or doesn't need validation. If the
-     * conditional get succeeds, these will be used for the response headers and
-     * body. If it fails, these be closed and set to null.
-     */
-    private ResponseHeaders cachedResponseHeaders;
-    private InputStream cachedResponseBody;
-
-    /**
-     * True if the socket connection should be released to the connection pool
-     * when the response has been fully read.
-     */
-    private boolean automaticallyReleaseConnectionToPool;
-
-    /** True if the socket connection is no longer needed by this engine. */
-    private boolean connectionReleased;
-
-    /**
-     * @param requestHeaders the client's supplied request headers. This class
-     *     creates a private copy that it can mutate.
-     * @param connection the connection used for an intermediate response
-     *     immediately prior to this request/response pair, such as a same-host
-     *     redirect. This engine assumes ownership of the connection and must
-     *     release it when it is unneeded.
-     */
-    public HttpEngine(HttpURLConnectionImpl policy, String method, RawHeaders requestHeaders,
-            HttpConnection connection, RetryableOutputStream requestBodyOut) throws IOException {
-        this.policy = policy;
-        this.method = method;
-        this.connection = connection;
-        this.requestBodyOut = requestBodyOut;
-
-        try {
-            uri = policy.getURL().toURILenient();
-        } catch (URISyntaxException e) {
-            throw new IOException(e);
-        }
-
-        this.requestHeaders = new RequestHeaders(uri, new RawHeaders(requestHeaders));
-    }
-
-    public URI getUri() {
-        return uri;
-    }
-
-    /**
-     * Figures out what the response source will be, and opens a socket to that
-     * source if necessary. Prepares the request headers and gets ready to start
-     * writing the request body if it exists.
-     */
-    public final void sendRequest() throws IOException {
-        if (responseSource != null) {
-            return;
-        }
-
-        prepareRawRequestHeaders();
-        initResponseSource();
-        if (responseCache instanceof ExtendedResponseCache) {
-            ((ExtendedResponseCache) responseCache).trackResponse(responseSource);
-        }
-
-        /*
-         * The raw response source may require the network, but the request
-         * headers may forbid network use. In that case, dispose of the network
-         * response and use a GATEWAY_TIMEOUT response instead, as specified
-         * by http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4.
-         */
-        if (requestHeaders.isOnlyIfCached() && responseSource.requiresConnection()) {
-            if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
-                IoUtils.closeQuietly(cachedResponseBody);
-            }
-            this.responseSource = ResponseSource.CACHE;
-            this.cacheResponse = GATEWAY_TIMEOUT_RESPONSE;
-            RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(cacheResponse.getHeaders());
-            setResponse(new ResponseHeaders(uri, rawResponseHeaders), cacheResponse.getBody());
-        }
-
-        if (responseSource.requiresConnection()) {
-            sendSocketRequest();
-        } else if (connection != null) {
-            HttpConnectionPool.INSTANCE.recycle(connection);
-            connection = null;
-        }
-    }
-
-    /**
-     * Initialize the source for this response. It may be corrected later if the
-     * request headers forbids network use.
-     */
-    private void initResponseSource() throws IOException {
-        responseSource = ResponseSource.NETWORK;
-        if (!policy.getUseCaches() || responseCache == null) {
-            return;
-        }
-
-        CacheResponse candidate = responseCache.get(uri, method,
-                requestHeaders.getHeaders().toMultimap());
-        if (candidate == null) {
-            return;
-        }
-
-        Map<String, List<String>> responseHeadersMap = candidate.getHeaders();
-        cachedResponseBody = candidate.getBody();
-        if (!acceptCacheResponseType(candidate)
-                || responseHeadersMap == null
-                || cachedResponseBody == null) {
-            IoUtils.closeQuietly(cachedResponseBody);
-            return;
-        }
-
-        RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(responseHeadersMap);
-        cachedResponseHeaders = new ResponseHeaders(uri, rawResponseHeaders);
-        long now = System.currentTimeMillis();
-        this.responseSource = cachedResponseHeaders.chooseResponseSource(now, requestHeaders);
-        if (responseSource == ResponseSource.CACHE) {
-            this.cacheResponse = candidate;
-            setResponse(cachedResponseHeaders, cachedResponseBody);
-        } else if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
-            this.cacheResponse = candidate;
-        } else if (responseSource == ResponseSource.NETWORK) {
-            IoUtils.closeQuietly(cachedResponseBody);
-        } else {
-            throw new AssertionError();
-        }
-    }
-
-    private void sendSocketRequest() throws IOException {
-        if (connection == null) {
-            connect();
-        }
-
-        if (socketOut != null || requestOut != null || socketIn != null) {
-            throw new IllegalStateException();
-        }
-
-        socketOut = connection.getOutputStream();
-        requestOut = socketOut;
-        socketIn = connection.getInputStream();
-
-        if (hasRequestBody()) {
-            initRequestBodyOut();
-        }
-    }
-
-    /**
-     * Connect to the origin server either directly or via a proxy.
-     */
-    protected void connect() throws IOException {
-        if (connection == null) {
-            connection = openSocketConnection();
-        }
-    }
-
-    protected final HttpConnection openSocketConnection() throws IOException {
-        HttpConnection result = HttpConnection.connect(uri, getSslSocketFactory(),
-                policy.getProxy(), requiresTunnel(), policy.getConnectTimeout());
-        Proxy proxy = result.getAddress().getProxy();
-        if (proxy != null) {
-            policy.setProxy(proxy);
-        }
-        result.setSoTimeout(policy.getReadTimeout());
-        return result;
-    }
-
-    protected void initRequestBodyOut() throws IOException {
-        int chunkLength = policy.getChunkLength();
-        if (chunkLength > 0 || requestHeaders.isChunked()) {
-            sendChunked = true;
-            if (chunkLength == -1) {
-                chunkLength = DEFAULT_CHUNK_LENGTH;
-            }
-        }
-
-        if (socketOut == null) {
-            throw new IllegalStateException("No socket to write to; was a POST cached?");
-        }
-
-        if (httpMinorVersion == 0) {
-            sendChunked = false;
-        }
-
-        int fixedContentLength = policy.getFixedContentLength();
-        if (requestBodyOut != null) {
-            // request body was already initialized by the predecessor HTTP engine
-        } else if (fixedContentLength != -1) {
-            writeRequestHeaders(fixedContentLength);
-            requestBodyOut = new FixedLengthOutputStream(requestOut, fixedContentLength);
-        } else if (sendChunked) {
-            writeRequestHeaders(-1);
-            requestBodyOut = new ChunkedOutputStream(requestOut, chunkLength);
-        } else if (requestHeaders.getContentLength() != -1) {
-            writeRequestHeaders(requestHeaders.getContentLength());
-            requestBodyOut = new RetryableOutputStream(requestHeaders.getContentLength());
-        } else {
-            requestBodyOut = new RetryableOutputStream();
-        }
-    }
-
-    /**
-     * @param body the response body, or null if it doesn't exist or isn't
-     *     available.
-     */
-    private void setResponse(ResponseHeaders headers, InputStream body) throws IOException {
-        if (this.responseBodyIn != null) {
-            throw new IllegalStateException();
-        }
-        this.responseHeaders = headers;
-        this.httpMinorVersion = responseHeaders.getHeaders().getHttpMinorVersion();
-        if (body != null) {
-            initContentStream(body);
-        }
-    }
-
-    private boolean hasRequestBody() {
-        return method == POST || method == PUT;
-    }
-
-    /**
-     * Returns the request body or null if this request doesn't have a body.
-     */
-    public final OutputStream getRequestBody() {
-        if (responseSource == null) {
-            throw new IllegalStateException();
-        }
-        return requestBodyOut;
-    }
-
-    public final boolean hasResponse() {
-        return responseHeaders != null;
-    }
-
-    public final RequestHeaders getRequestHeaders() {
-        return requestHeaders;
-    }
-
-    public final ResponseHeaders getResponseHeaders() {
-        if (responseHeaders == null) {
-            throw new IllegalStateException();
-        }
-        return responseHeaders;
-    }
-
-    public final int getResponseCode() {
-        if (responseHeaders == null) {
-            throw new IllegalStateException();
-        }
-        return responseHeaders.getHeaders().getResponseCode();
-    }
-
-    public final InputStream getResponseBody() {
-        if (responseHeaders == null) {
-            throw new IllegalStateException();
-        }
-        return responseBodyIn;
-    }
-
-    public final CacheResponse getCacheResponse() {
-        return cacheResponse;
-    }
-
-    public final HttpConnection getConnection() {
-        return connection;
-    }
-
-    public final boolean hasRecycledConnection() {
-        return connection != null && connection.isRecycled();
-    }
-
-    /**
-     * Returns true if {@code cacheResponse} is of the right type. This
-     * condition is necessary but not sufficient for the cached response to
-     * be used.
-     */
-    protected boolean acceptCacheResponseType(CacheResponse cacheResponse) {
-        return true;
-    }
-
-    private void maybeCache() throws IOException {
-        // Never cache responses to proxy CONNECT requests.
-        if (method == CONNECT) {
-            return;
-        }
-
-        // Are we caching at all?
-        if (!policy.getUseCaches() || responseCache == null) {
-            return;
-        }
-
-        // Should we cache this response for this request?
-        if (!responseHeaders.isCacheable(requestHeaders)) {
-            return;
-        }
-
-        // Offer this request to the cache.
-        cacheRequest = responseCache.put(uri, getHttpConnectionToCache());
-    }
-
-    protected HttpURLConnection getHttpConnectionToCache() {
-        return policy;
-    }
-
-    /**
-     * Cause the socket connection to be released to the connection pool when
-     * it is no longer needed. If it is already unneeded, it will be pooled
-     * immediately.
-     */
-    public final void automaticallyReleaseConnectionToPool() {
-        automaticallyReleaseConnectionToPool = true;
-        if (connection != null && connectionReleased) {
-            HttpConnectionPool.INSTANCE.recycle(connection);
-            connection = null;
-        }
-    }
-
-    public final void markConnectionAsRecycled() {
-        if (connection != null) {
-            connection.setRecycled();
-        }
-    }
-
-    /**
-     * Releases this engine so that its resources may be either reused or
-     * closed.
-     */
-    public final void release(boolean reusable) {
-        // If the response body comes from the cache, close it.
-        if (responseBodyIn == cachedResponseBody) {
-            IoUtils.closeQuietly(responseBodyIn);
-        }
-
-        if (!connectionReleased && connection != null) {
-            connectionReleased = true;
-
-            // We cannot reuse sockets that have incomplete output.
-            if (requestBodyOut != null && !requestBodyOut.closed) {
-                reusable = false;
-            }
-
-            // If the request specified that the connection shouldn't be reused,
-            // don't reuse it. This advice doesn't apply to CONNECT requests because
-            // the "Connection: close" header goes the origin server, not the proxy.
-            if (requestHeaders.hasConnectionClose() && method != CONNECT) {
-                reusable = false;
-            }
-
-            // If the response specified that the connection shouldn't be reused, don't reuse it.
-            if (responseHeaders != null && responseHeaders.hasConnectionClose()) {
-                reusable = false;
-            }
-
-            if (responseBodyIn instanceof UnknownLengthHttpInputStream) {
-                reusable = false;
-            }
-
-            if (reusable && responseBodyIn != null) {
-                // We must discard the response body before the connection can be reused.
-                try {
-                    Streams.skipAll(responseBodyIn);
-                } catch (IOException e) {
-                    reusable = false;
-                }
-            }
-
-            if (!reusable) {
-                connection.closeSocketAndStreams();
-                connection = null;
-            } else if (automaticallyReleaseConnectionToPool) {
-                HttpConnectionPool.INSTANCE.recycle(connection);
-                connection = null;
-            }
-        }
-    }
-
-    private void initContentStream(InputStream transferStream) throws IOException {
-        if (transparentGzip && responseHeaders.isContentEncodingGzip()) {
-            /*
-             * If the response was transparently gzipped, remove the gzip header field
-             * so clients don't double decompress. http://b/3009828
-             *
-             * Also remove the Content-Length in this case because it contains the length
-             * of the gzipped response. This isn't terribly useful and is dangerous because
-             * clients can query the content length, but not the content encoding.
-             */
-            responseHeaders.stripContentEncoding();
-            responseHeaders.stripContentLength();
-            responseBodyIn = new GZIPInputStream(transferStream);
-        } else {
-            responseBodyIn = transferStream;
-        }
-    }
-
-    private InputStream getTransferStream() throws IOException {
-        if (!hasResponseBody()) {
-            return new FixedLengthInputStream(socketIn, cacheRequest, this, 0);
-        }
-
-        if (responseHeaders.isChunked()) {
-            return new ChunkedInputStream(socketIn, cacheRequest, this);
-        }
-
-        if (responseHeaders.getContentLength() != -1) {
-            return new FixedLengthInputStream(socketIn, cacheRequest, this,
-                    responseHeaders.getContentLength());
-        }
-
-        /*
-         * Wrap the input stream from the HttpConnection (rather than
-         * just returning "socketIn" directly here), so that we can control
-         * its use after the reference escapes.
-         */
-        return new UnknownLengthHttpInputStream(socketIn, cacheRequest, this);
-    }
-
-    private void readResponseHeaders() throws IOException {
-        RawHeaders headers;
-        do {
-            headers = new RawHeaders();
-            headers.setStatusLine(Streams.readAsciiLine(socketIn));
-            readHeaders(headers);
-        } while (headers.getResponseCode() == HTTP_CONTINUE);
-        setResponse(new ResponseHeaders(uri, headers), null);
-    }
-
-    /**
-     * Returns true if the response must have a (possibly 0-length) body.
-     * See RFC 2616 section 4.3.
-     */
-    public final boolean hasResponseBody() {
-        int responseCode = responseHeaders.getHeaders().getResponseCode();
-
-        // HEAD requests never yield a body regardless of the response headers.
-        if (method == HEAD) {
-            return false;
-        }
-
-        if (method != CONNECT
-                && (responseCode < HTTP_CONTINUE || responseCode >= 200)
-                && responseCode != HttpURLConnectionImpl.HTTP_NO_CONTENT
-                && responseCode != HttpURLConnectionImpl.HTTP_NOT_MODIFIED) {
-            return true;
-        }
-
-        /*
-         * If the Content-Length or Transfer-Encoding headers disagree with the
-         * response code, the response is malformed. For best compatibility, we
-         * honor the headers.
-         */
-        if (responseHeaders.getContentLength() != -1 || responseHeaders.isChunked()) {
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Trailers are headers included after the last chunk of a response encoded
-     * with chunked encoding.
-     */
-    final void readTrailers() throws IOException {
-        readHeaders(responseHeaders.getHeaders());
-    }
-
-    private void readHeaders(RawHeaders headers) throws IOException {
-        // parse the result headers until the first blank line
-        String line;
-        while (!(line = Streams.readAsciiLine(socketIn)).isEmpty()) {
-            headers.addLine(line);
-        }
-
-        CookieHandler cookieHandler = CookieHandler.getDefault();
-        if (cookieHandler != null) {
-            cookieHandler.put(uri, headers.toMultimap());
-        }
-    }
-
-    /**
-     * Prepares the HTTP headers and sends them to the server.
-     *
-     * <p>For streaming requests with a body, headers must be prepared
-     * <strong>before</strong> the output stream has been written to. Otherwise
-     * the body would need to be buffered!
-     *
-     * <p>For non-streaming requests with a body, headers must be prepared
-     * <strong>after</strong> the output stream has been written to and closed.
-     * This ensures that the {@code Content-Length} header field receives the
-     * proper value.
-     *
-     * @param contentLength the number of bytes in the request body, or -1 if
-     *      the request body length is unknown.
-     */
-    private void writeRequestHeaders(int contentLength) throws IOException {
-        if (sentRequestMillis != -1) {
-            throw new IllegalStateException();
-        }
-
-        RawHeaders headersToSend = getNetworkRequestHeaders();
-        byte[] bytes = headersToSend.toHeaderString().getBytes(Charsets.ISO_8859_1);
-
-        if (contentLength != -1 && bytes.length + contentLength <= MAX_REQUEST_BUFFER_LENGTH) {
-            requestOut = new BufferedOutputStream(socketOut, bytes.length + contentLength);
-        }
-
-        sentRequestMillis = System.currentTimeMillis();
-        requestOut.write(bytes);
-    }
-
-    /**
-     * Returns the headers to send on a network request.
-     *
-     * <p>This adds the content length and content-type headers, which are
-     * neither needed nor known when querying the response cache.
-     *
-     * <p>It updates the status line, which may need to be fully qualified if
-     * the connection is using a proxy.
-     */
-    protected RawHeaders getNetworkRequestHeaders() throws IOException {
-        requestHeaders.getHeaders().setStatusLine(getRequestLine());
-
-        int fixedContentLength = policy.getFixedContentLength();
-        if (fixedContentLength != -1) {
-            requestHeaders.setContentLength(fixedContentLength);
-        } else if (sendChunked) {
-            requestHeaders.setChunked();
-        } else if (requestBodyOut instanceof RetryableOutputStream) {
-            int contentLength = ((RetryableOutputStream) requestBodyOut).contentLength();
-            requestHeaders.setContentLength(contentLength);
-        }
-
-        return requestHeaders.getHeaders();
-    }
-
-    /**
-     * Populates requestHeaders with defaults and cookies.
-     *
-     * <p>This client doesn't specify a default {@code Accept} header because it
-     * doesn't know what content types the application is interested in.
-     */
-    private void prepareRawRequestHeaders() throws IOException {
-        requestHeaders.getHeaders().setStatusLine(getRequestLine());
-
-        if (requestHeaders.getUserAgent() == null) {
-            requestHeaders.setUserAgent(getDefaultUserAgent());
-        }
-
-        if (requestHeaders.getHost() == null) {
-            requestHeaders.setHost(getOriginAddress(policy.getURL()));
-        }
-
-        if (httpMinorVersion > 0 && requestHeaders.getConnection() == null) {
-            requestHeaders.setConnection("Keep-Alive");
-        }
-
-        if (requestHeaders.getAcceptEncoding() == null) {
-            transparentGzip = true;
-            requestHeaders.setAcceptEncoding("gzip");
-        }
-
-        if (hasRequestBody() && requestHeaders.getContentType() == null) {
-            requestHeaders.setContentType("application/x-www-form-urlencoded");
-        }
-
-        long ifModifiedSince = policy.getIfModifiedSince();
-        if (ifModifiedSince != 0) {
-            requestHeaders.setIfModifiedSince(new Date(ifModifiedSince));
-        }
-
-        CookieHandler cookieHandler = CookieHandler.getDefault();
-        if (cookieHandler != null) {
-            requestHeaders.addCookies(
-                    cookieHandler.get(uri, requestHeaders.getHeaders().toMultimap()));
-        }
-    }
-
-    private String getRequestLine() {
-        String protocol = (httpMinorVersion == 0) ? "HTTP/1.0" : "HTTP/1.1";
-        return method + " " + requestString() + " " + protocol;
-    }
-
-    private String requestString() {
-        URL url = policy.getURL();
-        if (includeAuthorityInRequestLine()) {
-            return url.toString();
-        } else {
-            String fileOnly = url.getFile();
-            if (fileOnly == null) {
-                fileOnly = "/";
-            } else if (!fileOnly.startsWith("/")) {
-                fileOnly = "/" + fileOnly;
-            }
-            return fileOnly;
-        }
-    }
-
-    /**
-     * Returns true if the request line should contain the full URL with host
-     * and port (like "GET http://android.com/foo HTTP/1.1") or only the path
-     * (like "GET /foo HTTP/1.1").
-     *
-     * <p>This is non-final because for HTTPS it's never necessary to supply the
-     * full URL, even if a proxy is in use.
-     */
-    protected boolean includeAuthorityInRequestLine() {
-        return policy.usingProxy();
-    }
-
-    /**
-     * Returns the SSL configuration for connections created by this engine.
-     * We cannot reuse HTTPS connections if the socket factory has changed.
-     */
-    protected SSLSocketFactory getSslSocketFactory() {
-        return null;
-    }
-
-    protected final String getDefaultUserAgent() {
-        String agent = System.getProperty("http.agent");
-        return agent != null ? agent : ("Java" + System.getProperty("java.version"));
-    }
-
-    protected final String getOriginAddress(URL url) {
-        int port = url.getPort();
-        String result = url.getHost();
-        if (port > 0 && port != policy.getDefaultPort()) {
-            result = result + ":" + port;
-        }
-        return result;
-    }
-
-    protected boolean requiresTunnel() {
-        return false;
-    }
-
-    /**
-     * Flushes the remaining request header and body, parses the HTTP response
-     * headers and starts reading the HTTP response body if it exists.
-     */
-    public final void readResponse() throws IOException {
-        if (hasResponse()) {
-            return;
-        }
-
-        if (responseSource == null) {
-            throw new IllegalStateException("readResponse() without sendRequest()");
-        }
-
-        if (!responseSource.requiresConnection()) {
-            return;
-        }
-
-        if (sentRequestMillis == -1) {
-            int contentLength = requestBodyOut instanceof RetryableOutputStream
-                    ? ((RetryableOutputStream) requestBodyOut).contentLength()
-                    : -1;
-            writeRequestHeaders(contentLength);
-        }
-
-        if (requestBodyOut != null) {
-            requestBodyOut.close();
-            if (requestBodyOut instanceof RetryableOutputStream) {
-                ((RetryableOutputStream) requestBodyOut).writeToSocket(requestOut);
-            }
-        }
-
-        requestOut.flush();
-        requestOut = socketOut;
-
-        readResponseHeaders();
-        responseHeaders.setLocalTimestamps(sentRequestMillis, System.currentTimeMillis());
-
-        if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
-            if (cachedResponseHeaders.validate(responseHeaders)) {
-                release(true);
-                ResponseHeaders combinedHeaders = cachedResponseHeaders.combine(responseHeaders);
-                setResponse(combinedHeaders, cachedResponseBody);
-                if (responseCache instanceof ExtendedResponseCache) {
-                    ExtendedResponseCache httpResponseCache = (ExtendedResponseCache) responseCache;
-                    httpResponseCache.trackConditionalCacheHit();
-                    httpResponseCache.update(cacheResponse, getHttpConnectionToCache());
-                }
-                return;
-            } else {
-                IoUtils.closeQuietly(cachedResponseBody);
-            }
-        }
-
-        if (hasResponseBody()) {
-            maybeCache(); // reentrant. this calls into user code which may call back into this!
-        }
-
-        initContentStream(getTransferStream());
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpHandler.java b/luni/src/main/java/libcore/net/http/HttpHandler.java
deleted file mode 100644
index e168f42..0000000
--- a/luni/src/main/java/libcore/net/http/HttpHandler.java
+++ /dev/null
@@ -1,42 +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 libcore.net.http;
-
-import java.io.IOException;
-import java.net.Proxy;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-
-public final class HttpHandler extends URLStreamHandler {
-
-    @Override protected URLConnection openConnection(URL u) throws IOException {
-        return new HttpURLConnectionImpl(u, getDefaultPort());
-    }
-
-    @Override protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {
-        if (url == null || proxy == null) {
-            throw new IllegalArgumentException("url == null || proxy == null");
-        }
-        return new HttpURLConnectionImpl(url, getDefaultPort(), proxy);
-    }
-
-    @Override protected int getDefaultPort() {
-        return 80;
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpResponseCache.java b/luni/src/main/java/libcore/net/http/HttpResponseCache.java
deleted file mode 100644
index 1a9dfd1..0000000
--- a/luni/src/main/java/libcore/net/http/HttpResponseCache.java
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * Copyright (C) 2010 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.net.http;
-
-import java.io.BufferedWriter;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FilterInputStream;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.ExtendedResponseCache;
-import java.net.HttpURLConnection;
-import java.net.ResponseCache;
-import java.net.ResponseSource;
-import java.net.SecureCacheResponse;
-import java.net.URI;
-import java.net.URLConnection;
-import java.nio.charset.Charsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import libcore.io.Base64;
-import libcore.io.DiskLruCache;
-import libcore.io.IoUtils;
-import libcore.io.StrictLineReader;
-
-/**
- * Cache responses in a directory on the file system. Most clients should use
- * {@code android.net.HttpResponseCache}, the stable, documented front end for
- * this.
- */
-public final class HttpResponseCache extends ResponseCache implements ExtendedResponseCache {
-    // TODO: add APIs to iterate the cache?
-    private static final int VERSION = 201105;
-    private static final int ENTRY_METADATA = 0;
-    private static final int ENTRY_BODY = 1;
-    private static final int ENTRY_COUNT = 2;
-
-    private final DiskLruCache cache;
-
-    /* read and write statistics, all guarded by 'this' */
-    private int writeSuccessCount;
-    private int writeAbortCount;
-    private int networkCount;
-    private int hitCount;
-    private int requestCount;
-
-    public HttpResponseCache(File directory, long maxSize) throws IOException {
-        cache = DiskLruCache.open(directory, VERSION, ENTRY_COUNT, maxSize);
-    }
-
-    private String uriToKey(URI uri) {
-        try {
-            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
-            byte[] md5bytes = messageDigest.digest(uri.toString().getBytes(Charsets.UTF_8));
-            return IntegralToString.bytesToHexString(md5bytes, false);
-        } catch (NoSuchAlgorithmException e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    @Override public CacheResponse get(URI uri, String requestMethod,
-            Map<String, List<String>> requestHeaders) {
-        String key = uriToKey(uri);
-        DiskLruCache.Snapshot snapshot;
-        Entry entry;
-        try {
-            snapshot = cache.get(key);
-            if (snapshot == null) {
-                return null;
-            }
-            entry = new Entry(snapshot.getInputStream(ENTRY_METADATA));
-        } catch (IOException e) {
-            // Give up because the cache cannot be read.
-            return null;
-        }
-
-        if (!entry.matches(uri, requestMethod, requestHeaders)) {
-            snapshot.close();
-            return null;
-        }
-
-        return entry.isHttps()
-                ? new EntrySecureCacheResponse(entry, snapshot)
-                : new EntryCacheResponse(entry, snapshot);
-    }
-
-    @Override public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
-        if (!(urlConnection instanceof HttpURLConnection)) {
-            return null;
-        }
-
-        HttpURLConnection httpConnection = (HttpURLConnection) urlConnection;
-        String requestMethod = httpConnection.getRequestMethod();
-        String key = uriToKey(uri);
-
-        if (requestMethod.equals(HttpEngine.POST)
-                || requestMethod.equals(HttpEngine.PUT)
-                || requestMethod.equals(HttpEngine.DELETE)) {
-            try {
-                cache.remove(key);
-            } catch (IOException ignored) {
-                // The cache cannot be written.
-            }
-            return null;
-        } else if (!requestMethod.equals(HttpEngine.GET)) {
-            /*
-             * Don't cache non-GET responses. We're technically allowed to cache
-             * HEAD requests and some POST requests, but the complexity of doing
-             * so is high and the benefit is low.
-             */
-            return null;
-        }
-
-        HttpEngine httpEngine = getHttpEngine(httpConnection);
-        if (httpEngine == null) {
-            // Don't cache unless the HTTP implementation is ours.
-            return null;
-        }
-
-        ResponseHeaders response = httpEngine.getResponseHeaders();
-        if (response.hasVaryAll()) {
-            return null;
-        }
-
-        RawHeaders varyHeaders = httpEngine.getRequestHeaders().getHeaders().getAll(
-                response.getVaryFields());
-        Entry entry = new Entry(uri, varyHeaders, httpConnection);
-        DiskLruCache.Editor editor = null;
-        try {
-            editor = cache.edit(key);
-            if (editor == null) {
-                return null;
-            }
-            entry.writeTo(editor);
-            return new CacheRequestImpl(editor);
-        } catch (IOException e) {
-            abortQuietly(editor);
-            return null;
-        }
-    }
-
-    /**
-     * Handles a conditional request hit by updating the stored cache response
-     * with the headers from {@code httpConnection}. The cached response body is
-     * not updated. If the stored response has changed since {@code
-     * conditionalCacheHit} was returned, this does nothing.
-     */
-    public void update(CacheResponse conditionalCacheHit, HttpURLConnection httpConnection) {
-        HttpEngine httpEngine = getHttpEngine(httpConnection);
-        URI uri = httpEngine.getUri();
-        ResponseHeaders response = httpEngine.getResponseHeaders();
-        RawHeaders varyHeaders = httpEngine.getRequestHeaders().getHeaders()
-                .getAll(response.getVaryFields());
-        Entry entry = new Entry(uri, varyHeaders, httpConnection);
-        DiskLruCache.Snapshot snapshot = (conditionalCacheHit instanceof EntryCacheResponse)
-                ? ((EntryCacheResponse) conditionalCacheHit).snapshot
-                : ((EntrySecureCacheResponse) conditionalCacheHit).snapshot;
-        DiskLruCache.Editor editor = null;
-        try {
-            editor = snapshot.edit(); // returns null if snapshot is not current
-            if (editor != null) {
-                entry.writeTo(editor);
-                editor.commit();
-            }
-        } catch (IOException e) {
-            abortQuietly(editor);
-        }
-    }
-
-    private void abortQuietly(DiskLruCache.Editor editor) {
-        // Give up because the cache cannot be written.
-        try {
-            if (editor != null) {
-                editor.abort();
-            }
-        } catch (IOException ignored) {
-        }
-    }
-
-    private HttpEngine getHttpEngine(HttpURLConnection httpConnection) {
-        if (httpConnection instanceof HttpURLConnectionImpl) {
-            return ((HttpURLConnectionImpl) httpConnection).getHttpEngine();
-        } else if (httpConnection instanceof HttpsURLConnectionImpl) {
-            return ((HttpsURLConnectionImpl) httpConnection).getHttpEngine();
-        } else {
-            return null;
-        }
-    }
-
-    public DiskLruCache getCache() {
-        return cache;
-    }
-
-    public synchronized int getWriteAbortCount() {
-        return writeAbortCount;
-    }
-
-    public synchronized int getWriteSuccessCount() {
-        return writeSuccessCount;
-    }
-
-    public synchronized void trackResponse(ResponseSource source) {
-        requestCount++;
-
-        switch (source) {
-        case CACHE:
-            hitCount++;
-            break;
-        case CONDITIONAL_CACHE:
-        case NETWORK:
-            networkCount++;
-            break;
-        }
-    }
-
-    public synchronized void trackConditionalCacheHit() {
-        hitCount++;
-    }
-
-    public synchronized int getNetworkCount() {
-        return networkCount;
-    }
-
-    public synchronized int getHitCount() {
-        return hitCount;
-    }
-
-    public synchronized int getRequestCount() {
-        return requestCount;
-    }
-
-    private final class CacheRequestImpl extends CacheRequest {
-        private final DiskLruCache.Editor editor;
-        private OutputStream cacheOut;
-        private boolean done;
-        private OutputStream body;
-
-        public CacheRequestImpl(final DiskLruCache.Editor editor) throws IOException {
-            this.editor = editor;
-            this.cacheOut = editor.newOutputStream(ENTRY_BODY);
-            this.body = new FilterOutputStream(cacheOut) {
-                @Override public void close() throws IOException {
-                    synchronized (HttpResponseCache.this) {
-                        if (done) {
-                            return;
-                        }
-                        done = true;
-                        writeSuccessCount++;
-                    }
-                    super.close();
-                    editor.commit();
-                }
-
-                @Override
-                public void write(byte[] buffer, int offset, int length) throws IOException {
-                    // Since we don't override "write(int oneByte)", we can write directly to "out"
-                    // and avoid the inefficient implementation from the FilterOutputStream.
-                    out.write(buffer, offset, length);
-                }
-            };
-        }
-
-        @Override public void abort() {
-            synchronized (HttpResponseCache.this) {
-                if (done) {
-                    return;
-                }
-                done = true;
-                writeAbortCount++;
-            }
-            IoUtils.closeQuietly(cacheOut);
-            try {
-                editor.abort();
-            } catch (IOException ignored) {
-            }
-        }
-
-        @Override public OutputStream getBody() throws IOException {
-            return body;
-        }
-    }
-
-    private static final class Entry {
-        private final String uri;
-        private final RawHeaders varyHeaders;
-        private final String requestMethod;
-        private final RawHeaders responseHeaders;
-        private final String cipherSuite;
-        private final Certificate[] peerCertificates;
-        private final Certificate[] localCertificates;
-
-        /*
-         * Reads an entry from an input stream. A typical entry looks like this:
-         *   http://google.com/foo
-         *   GET
-         *   2
-         *   Accept-Language: fr-CA
-         *   Accept-Charset: UTF-8
-         *   HTTP/1.1 200 OK
-         *   3
-         *   Content-Type: image/png
-         *   Content-Length: 100
-         *   Cache-Control: max-age=600
-         *
-         * A typical HTTPS file looks like this:
-         *   https://google.com/foo
-         *   GET
-         *   2
-         *   Accept-Language: fr-CA
-         *   Accept-Charset: UTF-8
-         *   HTTP/1.1 200 OK
-         *   3
-         *   Content-Type: image/png
-         *   Content-Length: 100
-         *   Cache-Control: max-age=600
-         *
-         *   AES_256_WITH_MD5
-         *   2
-         *   base64-encoded peerCertificate[0]
-         *   base64-encoded peerCertificate[1]
-         *   -1
-         *
-         * The file is newline separated. The first two lines are the URL and
-         * the request method. Next is the number of HTTP Vary request header
-         * lines, followed by those lines.
-         *
-         * Next is the response status line, followed by the number of HTTP
-         * response header lines, followed by those lines.
-         *
-         * HTTPS responses also contain SSL session information. This begins
-         * with a blank line, and then a line containing the cipher suite. Next
-         * is the length of the peer certificate chain. These certificates are
-         * base64-encoded and appear each on their own line. The next line
-         * contains the length of the local certificate chain. These
-         * certificates are also base64-encoded and appear each on their own
-         * line. A length of -1 is used to encode a null array.
-         */
-        public Entry(InputStream in) throws IOException {
-            try {
-                StrictLineReader reader = new StrictLineReader(in, Charsets.US_ASCII);
-                uri = reader.readLine();
-                requestMethod = reader.readLine();
-                varyHeaders = new RawHeaders();
-                int varyRequestHeaderLineCount = reader.readInt();
-                for (int i = 0; i < varyRequestHeaderLineCount; i++) {
-                    varyHeaders.addLine(reader.readLine());
-                }
-
-                responseHeaders = new RawHeaders();
-                responseHeaders.setStatusLine(reader.readLine());
-                int responseHeaderLineCount = reader.readInt();
-                for (int i = 0; i < responseHeaderLineCount; i++) {
-                    responseHeaders.addLine(reader.readLine());
-                }
-
-                if (isHttps()) {
-                    String blank = reader.readLine();
-                    if (!blank.isEmpty()) {
-                        throw new IOException("expected \"\" but was \"" + blank + "\"");
-                    }
-                    cipherSuite = reader.readLine();
-                    peerCertificates = readCertArray(reader);
-                    localCertificates = readCertArray(reader);
-                } else {
-                    cipherSuite = null;
-                    peerCertificates = null;
-                    localCertificates = null;
-                }
-            } finally {
-                in.close();
-            }
-        }
-
-        public Entry(URI uri, RawHeaders varyHeaders, HttpURLConnection httpConnection) {
-            this.uri = uri.toString();
-            this.varyHeaders = varyHeaders;
-            this.requestMethod = httpConnection.getRequestMethod();
-            this.responseHeaders = RawHeaders.fromMultimap(httpConnection.getHeaderFields());
-
-            if (isHttps()) {
-                HttpsURLConnection httpsConnection = (HttpsURLConnection) httpConnection;
-                cipherSuite = httpsConnection.getCipherSuite();
-                Certificate[] peerCertificatesNonFinal = null;
-                try {
-                    peerCertificatesNonFinal = httpsConnection.getServerCertificates();
-                } catch (SSLPeerUnverifiedException ignored) {
-                }
-                peerCertificates = peerCertificatesNonFinal;
-                localCertificates = httpsConnection.getLocalCertificates();
-            } else {
-                cipherSuite = null;
-                peerCertificates = null;
-                localCertificates = null;
-            }
-        }
-
-        public void writeTo(DiskLruCache.Editor editor) throws IOException {
-            OutputStream out = editor.newOutputStream(ENTRY_METADATA);
-            Writer writer = new BufferedWriter(new OutputStreamWriter(out, Charsets.UTF_8));
-
-            writer.write(uri + '\n');
-            writer.write(requestMethod + '\n');
-            writer.write(Integer.toString(varyHeaders.length()) + '\n');
-            for (int i = 0; i < varyHeaders.length(); i++) {
-                writer.write(varyHeaders.getFieldName(i) + ": "
-                        + varyHeaders.getValue(i) + '\n');
-            }
-
-            writer.write(responseHeaders.getStatusLine() + '\n');
-            writer.write(Integer.toString(responseHeaders.length()) + '\n');
-            for (int i = 0; i < responseHeaders.length(); i++) {
-                writer.write(responseHeaders.getFieldName(i) + ": "
-                        + responseHeaders.getValue(i) + '\n');
-            }
-
-            if (isHttps()) {
-                writer.write('\n');
-                writer.write(cipherSuite + '\n');
-                writeCertArray(writer, peerCertificates);
-                writeCertArray(writer, localCertificates);
-            }
-            writer.close();
-        }
-
-        private boolean isHttps() {
-            return uri.startsWith("https://");
-        }
-
-        private Certificate[] readCertArray(StrictLineReader reader) throws IOException {
-            int length = reader.readInt();
-            if (length == -1) {
-                return null;
-            }
-            try {
-                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
-                Certificate[] result = new Certificate[length];
-                for (int i = 0; i < result.length; i++) {
-                    String line = reader.readLine();
-                    byte[] bytes = Base64.decode(line.getBytes(Charsets.US_ASCII));
-                    result[i] = certificateFactory.generateCertificate(
-                            new ByteArrayInputStream(bytes));
-                }
-                return result;
-            } catch (CertificateException e) {
-                throw new IOException(e);
-            }
-        }
-
-        private void writeCertArray(Writer writer, Certificate[] certificates) throws IOException {
-            if (certificates == null) {
-                writer.write("-1\n");
-                return;
-            }
-            try {
-                writer.write(Integer.toString(certificates.length) + '\n');
-                for (Certificate certificate : certificates) {
-                    byte[] bytes = certificate.getEncoded();
-                    String line = Base64.encode(bytes);
-                    writer.write(line + '\n');
-                }
-            } catch (CertificateEncodingException e) {
-                throw new IOException(e);
-            }
-        }
-
-        public boolean matches(URI uri, String requestMethod,
-                Map<String, List<String>> requestHeaders) {
-            return this.uri.equals(uri.toString())
-                    && this.requestMethod.equals(requestMethod)
-                    && new ResponseHeaders(uri, responseHeaders)
-                            .varyMatches(varyHeaders.toMultimap(), requestHeaders);
-        }
-    }
-
-    /**
-     * Returns an input stream that reads the body of a snapshot, closing the
-     * snapshot when the stream is closed.
-     */
-    private static InputStream newBodyInputStream(final DiskLruCache.Snapshot snapshot) {
-        return new FilterInputStream(snapshot.getInputStream(ENTRY_BODY)) {
-            @Override public void close() throws IOException {
-                snapshot.close();
-                super.close();
-            }
-        };
-    }
-
-    static class EntryCacheResponse extends CacheResponse {
-        private final Entry entry;
-        private final DiskLruCache.Snapshot snapshot;
-        private final InputStream in;
-
-        public EntryCacheResponse(Entry entry, DiskLruCache.Snapshot snapshot) {
-            this.entry = entry;
-            this.snapshot = snapshot;
-            this.in = newBodyInputStream(snapshot);
-        }
-
-        @Override public Map<String, List<String>> getHeaders() {
-            return entry.responseHeaders.toMultimap();
-        }
-
-        @Override public InputStream getBody() {
-            return in;
-        }
-    }
-
-    static class EntrySecureCacheResponse extends SecureCacheResponse {
-        private final Entry entry;
-        private final DiskLruCache.Snapshot snapshot;
-        private final InputStream in;
-
-        public EntrySecureCacheResponse(Entry entry, DiskLruCache.Snapshot snapshot) {
-            this.entry = entry;
-            this.snapshot = snapshot;
-            this.in = newBodyInputStream(snapshot);
-        }
-
-        @Override public Map<String, List<String>> getHeaders() {
-            return entry.responseHeaders.toMultimap();
-        }
-
-        @Override public InputStream getBody() {
-            return in;
-        }
-
-        @Override public String getCipherSuite() {
-            return entry.cipherSuite;
-        }
-
-        @Override public List<Certificate> getServerCertificateChain()
-                throws SSLPeerUnverifiedException {
-            if (entry.peerCertificates == null || entry.peerCertificates.length == 0) {
-                throw new SSLPeerUnverifiedException(null);
-            }
-            return Arrays.asList(entry.peerCertificates.clone());
-        }
-
-        @Override public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
-            if (entry.peerCertificates == null || entry.peerCertificates.length == 0) {
-                throw new SSLPeerUnverifiedException(null);
-            }
-            return ((X509Certificate) entry.peerCertificates[0]).getSubjectX500Principal();
-        }
-
-        @Override public List<Certificate> getLocalCertificateChain() {
-            if (entry.localCertificates == null || entry.localCertificates.length == 0) {
-                return null;
-            }
-            return Arrays.asList(entry.localCertificates.clone());
-        }
-
-        @Override public Principal getLocalPrincipal() {
-            if (entry.localCertificates == null || entry.localCertificates.length == 0) {
-                return null;
-            }
-            return ((X509Certificate) entry.localCertificates[0]).getSubjectX500Principal();
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java b/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
deleted file mode 100644
index 3e6503f..0000000
--- a/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
+++ /dev/null
@@ -1,519 +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 libcore.net.http;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Authenticator;
-import java.net.HttpRetryException;
-import java.net.HttpURLConnection;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.PasswordAuthentication;
-import java.net.ProtocolException;
-import java.net.Proxy;
-import java.net.SocketPermission;
-import java.net.URL;
-import java.nio.charset.Charsets;
-import java.security.Permission;
-import java.util.List;
-import java.util.Map;
-import libcore.io.Base64;
-import libcore.io.IoUtils;
-
-/**
- * This implementation uses HttpEngine to send requests and receive responses.
- * This class may use multiple HttpEngines to follow redirects, authentication
- * retries, etc. to retrieve the final response body.
- *
- * <h3>What does 'connected' mean?</h3>
- * This class inherits a {@code connected} field from the superclass. That field
- * is <strong>not</strong> used to indicate not whether this URLConnection is
- * currently connected. Instead, it indicates whether a connection has ever been
- * attempted. Once a connection has been attempted, certain properties (request
- * header fields, request method, etc.) are immutable. Test the {@code
- * connection} field on this class for null/non-null to determine of an instance
- * is currently connected to a server.
- */
-class HttpURLConnectionImpl extends HttpURLConnection {
-
-    private final int defaultPort;
-
-    private Proxy proxy;
-
-    private final RawHeaders rawRequestHeaders = new RawHeaders();
-
-    private int redirectionCount;
-
-    protected IOException httpEngineFailure;
-    protected HttpEngine httpEngine;
-
-    protected HttpURLConnectionImpl(URL url, int port) {
-        super(url);
-        defaultPort = port;
-    }
-
-    protected HttpURLConnectionImpl(URL url, int port, Proxy proxy) {
-        this(url, port);
-        this.proxy = proxy;
-    }
-
-    @Override public final void connect() throws IOException {
-        initHttpEngine();
-        try {
-            httpEngine.sendRequest();
-        } catch (IOException e) {
-            httpEngineFailure = e;
-            throw e;
-        }
-    }
-
-    @Override public final void disconnect() {
-        // Calling disconnect() before a connection exists should have no effect.
-        if (httpEngine != null) {
-            // We close the response body here instead of in
-            // HttpEngine.release because that is called when input
-            // has been completely read from the underlying socket.
-            // However the response body can be a GZIPInputStream that
-            // still has unread data.
-            if (httpEngine.hasResponse()) {
-                IoUtils.closeQuietly(httpEngine.getResponseBody());
-            }
-            httpEngine.release(false);
-        }
-    }
-
-    /**
-     * Returns an input stream from the server in the case of error such as the
-     * requested file (txt, htm, html) is not found on the remote server.
-     */
-    @Override public final InputStream getErrorStream() {
-        try {
-            HttpEngine response = getResponse();
-            if (response.hasResponseBody()
-                    && response.getResponseCode() >= HTTP_BAD_REQUEST) {
-                return response.getResponseBody();
-            }
-            return null;
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Returns the value of the field at {@code position}. Returns null if there
-     * are fewer than {@code position} headers.
-     */
-    @Override public final String getHeaderField(int position) {
-        try {
-            return getResponse().getResponseHeaders().getHeaders().getValue(position);
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Returns the value of the field corresponding to the {@code fieldName}, or
-     * null if there is no such field. If the field has multiple values, the
-     * last value is returned.
-     */
-    @Override public final String getHeaderField(String fieldName) {
-        try {
-            RawHeaders rawHeaders = getResponse().getResponseHeaders().getHeaders();
-            return fieldName == null
-                    ? rawHeaders.getStatusLine()
-                    : rawHeaders.get(fieldName);
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    @Override public final String getHeaderFieldKey(int position) {
-        try {
-            return getResponse().getResponseHeaders().getHeaders().getFieldName(position);
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    @Override public final Map<String, List<String>> getHeaderFields() {
-        try {
-            return getResponse().getResponseHeaders().getHeaders().toMultimap();
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    @Override public final Map<String, List<String>> getRequestProperties() {
-        if (connected) {
-            throw new IllegalStateException(
-                    "Cannot access request header fields after connection is set");
-        }
-        return rawRequestHeaders.toMultimap();
-    }
-
-    @Override public final InputStream getInputStream() throws IOException {
-        if (!doInput) {
-            throw new ProtocolException("This protocol does not support input");
-        }
-
-        HttpEngine response = getResponse();
-
-        /*
-         * if the requested file does not exist, throw an exception formerly the
-         * Error page from the server was returned if the requested file was
-         * text/html this has changed to return FileNotFoundException for all
-         * file types
-         */
-        if (getResponseCode() >= HTTP_BAD_REQUEST) {
-            throw new FileNotFoundException(url.toString());
-        }
-
-        InputStream result = response.getResponseBody();
-        if (result == null) {
-            throw new IOException("No response body exists; responseCode=" + getResponseCode());
-        }
-        return result;
-    }
-
-    @Override public final OutputStream getOutputStream() throws IOException {
-        connect();
-
-        OutputStream result = httpEngine.getRequestBody();
-        if (result == null) {
-            throw new ProtocolException("method does not support a request body: " + method);
-        } else if (httpEngine.hasResponse()) {
-            throw new ProtocolException("cannot write request body after response has been read");
-        }
-
-        return result;
-    }
-
-    @Override public final Permission getPermission() throws IOException {
-        String connectToAddress = getConnectToHost() + ":" + getConnectToPort();
-        return new SocketPermission(connectToAddress, "connect, resolve");
-    }
-
-    private String getConnectToHost() {
-        return usingProxy()
-                ? ((InetSocketAddress) proxy.address()).getHostName()
-                : getURL().getHost();
-    }
-
-    private int getConnectToPort() {
-        int hostPort = usingProxy()
-                ? ((InetSocketAddress) proxy.address()).getPort()
-                : getURL().getPort();
-        return hostPort < 0 ? getDefaultPort() : hostPort;
-    }
-
-    @Override public final String getRequestProperty(String field) {
-        if (field == null) {
-            return null;
-        }
-        return rawRequestHeaders.get(field);
-    }
-
-    private void initHttpEngine() throws IOException {
-        if (httpEngineFailure != null) {
-            throw httpEngineFailure;
-        } else if (httpEngine != null) {
-            return;
-        }
-
-        connected = true;
-        try {
-            if (doOutput) {
-                if (method == HttpEngine.GET) {
-                    // they are requesting a stream to write to. This implies a POST method
-                    method = HttpEngine.POST;
-                } else if (method != HttpEngine.POST && method != HttpEngine.PUT) {
-                    // If the request method is neither POST nor PUT, then you're not writing
-                    throw new ProtocolException(method + " does not support writing");
-                }
-            }
-            httpEngine = newHttpEngine(method, rawRequestHeaders, null, null);
-        } catch (IOException e) {
-            httpEngineFailure = e;
-            throw e;
-        }
-    }
-
-    /**
-     * Create a new HTTP engine. This hook method is non-final so it can be
-     * overridden by HttpsURLConnectionImpl.
-     */
-    protected HttpEngine newHttpEngine(String method, RawHeaders requestHeaders,
-            HttpConnection connection, RetryableOutputStream requestBody) throws IOException {
-        return new HttpEngine(this, method, requestHeaders, connection, requestBody);
-    }
-
-    /**
-     * Aggressively tries to get the final HTTP response, potentially making
-     * many HTTP requests in the process in order to cope with redirects and
-     * authentication.
-     */
-    private HttpEngine getResponse() throws IOException {
-        initHttpEngine();
-
-        if (httpEngine.hasResponse()) {
-            return httpEngine;
-        }
-
-        while (true) {
-            try {
-                httpEngine.sendRequest();
-                httpEngine.readResponse();
-            } catch (IOException e) {
-                /*
-                 * If the connection was recycled, its staleness may have caused
-                 * the failure. Silently retry with a different connection.
-                 */
-                OutputStream requestBody = httpEngine.getRequestBody();
-                if (httpEngine.hasRecycledConnection()
-                        && (requestBody == null || requestBody instanceof RetryableOutputStream)) {
-                    httpEngine.release(false);
-                    httpEngine = newHttpEngine(method, rawRequestHeaders, null,
-                            (RetryableOutputStream) requestBody);
-                    continue;
-                }
-                httpEngineFailure = e;
-                throw e;
-            }
-
-            Retry retry = processResponseHeaders();
-            if (retry == Retry.NONE) {
-                httpEngine.automaticallyReleaseConnectionToPool();
-                return httpEngine;
-            }
-
-            /*
-             * The first request was insufficient. Prepare for another...
-             */
-            String retryMethod = method;
-            OutputStream requestBody = httpEngine.getRequestBody();
-
-            /*
-             * Although RFC 2616 10.3.2 specifies that a HTTP_MOVED_PERM
-             * redirect should keep the same method, Chrome, Firefox and the
-             * RI all issue GETs when following any redirect.
-             */
-            int responseCode = getResponseCode();
-            if (responseCode == HTTP_MULT_CHOICE || responseCode == HTTP_MOVED_PERM
-                    || responseCode == HTTP_MOVED_TEMP || responseCode == HTTP_SEE_OTHER) {
-                retryMethod = HttpEngine.GET;
-                requestBody = null;
-            }
-
-            if (requestBody != null && !(requestBody instanceof RetryableOutputStream)) {
-                throw new HttpRetryException("Cannot retry streamed HTTP body",
-                        httpEngine.getResponseCode());
-            }
-
-            if (retry == Retry.DIFFERENT_CONNECTION) {
-                httpEngine.automaticallyReleaseConnectionToPool();
-            } else {
-                httpEngine.markConnectionAsRecycled();
-            }
-
-            httpEngine.release(true);
-
-            httpEngine = newHttpEngine(retryMethod, rawRequestHeaders,
-                    httpEngine.getConnection(), (RetryableOutputStream) requestBody);
-        }
-    }
-
-    HttpEngine getHttpEngine() {
-        return httpEngine;
-    }
-
-    enum Retry {
-        NONE,
-        SAME_CONNECTION,
-        DIFFERENT_CONNECTION
-    }
-
-    /**
-     * Returns the retry action to take for the current response headers. The
-     * headers, proxy and target URL or this connection may be adjusted to
-     * prepare for a follow up request.
-     */
-    private Retry processResponseHeaders() throws IOException {
-        switch (getResponseCode()) {
-        case HTTP_PROXY_AUTH:
-            if (!usingProxy()) {
-                throw new IOException(
-                        "Received HTTP_PROXY_AUTH (407) code while not using proxy");
-            }
-            // fall-through
-        case HTTP_UNAUTHORIZED:
-            boolean credentialsFound = processAuthHeader(getResponseCode(),
-                    httpEngine.getResponseHeaders(), rawRequestHeaders);
-            return credentialsFound ? Retry.SAME_CONNECTION : Retry.NONE;
-
-        case HTTP_MULT_CHOICE:
-        case HTTP_MOVED_PERM:
-        case HTTP_MOVED_TEMP:
-        case HTTP_SEE_OTHER:
-            if (!getInstanceFollowRedirects()) {
-                return Retry.NONE;
-            }
-            if (++redirectionCount > HttpEngine.MAX_REDIRECTS) {
-                throw new ProtocolException("Too many redirects");
-            }
-            String location = getHeaderField("Location");
-            if (location == null) {
-                return Retry.NONE;
-            }
-            URL previousUrl = url;
-            url = new URL(previousUrl, location);
-            if (!previousUrl.getProtocol().equals(url.getProtocol())) {
-                return Retry.NONE; // the scheme changed; don't retry.
-            }
-            if (previousUrl.getHost().equals(url.getHost())
-                    && previousUrl.getEffectivePort() == url.getEffectivePort()) {
-                return Retry.SAME_CONNECTION;
-            } else {
-                return Retry.DIFFERENT_CONNECTION;
-            }
-
-        default:
-            return Retry.NONE;
-        }
-    }
-
-    /**
-     * React to a failed authorization response by looking up new credentials.
-     *
-     * @return true if credentials have been added to successorRequestHeaders
-     *     and another request should be attempted.
-     */
-    final boolean processAuthHeader(int responseCode, ResponseHeaders response,
-            RawHeaders successorRequestHeaders) throws IOException {
-        if (responseCode != HTTP_PROXY_AUTH && responseCode != HTTP_UNAUTHORIZED) {
-            throw new IllegalArgumentException("Bad response code: " + responseCode);
-        }
-
-        // keep asking for username/password until authorized
-        String challengeHeader = responseCode == HTTP_PROXY_AUTH
-                ? "Proxy-Authenticate"
-                : "WWW-Authenticate";
-        String credentials = getAuthorizationCredentials(response.getHeaders(), challengeHeader);
-        if (credentials == null) {
-            return false; // could not find credentials, end request cycle
-        }
-
-        // add authorization credentials, bypassing the already-connected check
-        String fieldName = responseCode == HTTP_PROXY_AUTH
-                ? "Proxy-Authorization"
-                : "Authorization";
-        successorRequestHeaders.set(fieldName, credentials);
-        return true;
-    }
-
-    /**
-     * Returns the authorization credentials on the base of provided challenge.
-     */
-    private String getAuthorizationCredentials(RawHeaders responseHeaders, String challengeHeader)
-            throws IOException {
-        List<Challenge> challenges = HeaderParser.parseChallenges(responseHeaders, challengeHeader);
-        if (challenges.isEmpty()) {
-            throw new IOException("No authentication challenges found");
-        }
-
-        for (Challenge challenge : challenges) {
-            // use the global authenticator to get the password
-            PasswordAuthentication auth = Authenticator.requestPasswordAuthentication(
-                    getConnectToInetAddress(), getConnectToPort(), url.getProtocol(),
-                    challenge.realm, challenge.scheme);
-            if (auth == null) {
-                continue;
-            }
-
-            // base64 encode the username and password
-            String usernameAndPassword = auth.getUserName() + ":" + new String(auth.getPassword());
-            byte[] bytes = usernameAndPassword.getBytes(Charsets.ISO_8859_1);
-            String encoded = Base64.encode(bytes);
-            return challenge.scheme + " " + encoded;
-        }
-
-        return null;
-    }
-
-    private InetAddress getConnectToInetAddress() throws IOException {
-        return usingProxy()
-                ? ((InetSocketAddress) proxy.address()).getAddress()
-                : InetAddress.getByName(getURL().getHost());
-    }
-
-    final int getDefaultPort() {
-        return defaultPort;
-    }
-
-    /** @see HttpURLConnection#setFixedLengthStreamingMode(int) */
-    final int getFixedContentLength() {
-        return fixedContentLength;
-    }
-
-    /** @see HttpURLConnection#setChunkedStreamingMode(int) */
-    final int getChunkLength() {
-        return chunkLength;
-    }
-
-    final Proxy getProxy() {
-        return proxy;
-    }
-
-    final void setProxy(Proxy proxy) {
-        this.proxy = proxy;
-    }
-
-    @Override public final boolean usingProxy() {
-        return (proxy != null && proxy.type() != Proxy.Type.DIRECT);
-    }
-
-    @Override public String getResponseMessage() throws IOException {
-        return getResponse().getResponseHeaders().getHeaders().getResponseMessage();
-    }
-
-    @Override public final int getResponseCode() throws IOException {
-        return getResponse().getResponseCode();
-    }
-
-    @Override public final void setRequestProperty(String field, String newValue) {
-        if (connected) {
-            throw new IllegalStateException("Cannot set request property after connection is made");
-        }
-        if (field == null) {
-            throw new NullPointerException("field == null");
-        }
-        rawRequestHeaders.set(field, newValue);
-    }
-
-    @Override public final void addRequestProperty(String field, String value) {
-        if (connected) {
-            throw new IllegalStateException("Cannot add request property after connection is made");
-        }
-        if (field == null) {
-            throw new NullPointerException("field == null");
-        }
-        rawRequestHeaders.add(field, value);
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpsHandler.java b/luni/src/main/java/libcore/net/http/HttpsHandler.java
deleted file mode 100644
index ed9ba72..0000000
--- a/luni/src/main/java/libcore/net/http/HttpsHandler.java
+++ /dev/null
@@ -1,42 +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 libcore.net.http;
-
-import java.io.IOException;
-import java.net.Proxy;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-
-public final class HttpsHandler extends URLStreamHandler {
-
-    @Override protected URLConnection openConnection(URL url) throws IOException {
-        return new HttpsURLConnectionImpl(url, getDefaultPort());
-    }
-
-    @Override protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {
-        if (url == null || proxy == null) {
-            throw new IllegalArgumentException("url == null || proxy == null");
-        }
-        return new HttpsURLConnectionImpl(url, getDefaultPort(), proxy);
-    }
-
-    @Override protected int getDefaultPort() {
-        return 443;
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpsURLConnectionImpl.java b/luni/src/main/java/libcore/net/http/HttpsURLConnectionImpl.java
deleted file mode 100644
index 9e3e4ef..0000000
--- a/luni/src/main/java/libcore/net/http/HttpsURLConnectionImpl.java
+++ /dev/null
@@ -1,580 +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 libcore.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheResponse;
-import java.net.HttpURLConnection;
-import java.net.ProtocolException;
-import java.net.Proxy;
-import java.net.SecureCacheResponse;
-import java.net.URL;
-import java.security.Permission;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.util.List;
-import java.util.Map;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-
-final class HttpsURLConnectionImpl extends HttpsURLConnection {
-
-    /** HttpUrlConnectionDelegate allows reuse of HttpURLConnectionImpl */
-    private final HttpUrlConnectionDelegate delegate;
-
-    protected HttpsURLConnectionImpl(URL url, int port) {
-        super(url);
-        delegate = new HttpUrlConnectionDelegate(url, port);
-    }
-
-    protected HttpsURLConnectionImpl(URL url, int port, Proxy proxy) {
-        super(url);
-        delegate = new HttpUrlConnectionDelegate(url, port, proxy);
-    }
-
-    private void checkConnected() {
-        if (delegate.getSSLSocket() == null) {
-            throw new IllegalStateException("Connection has not yet been established");
-        }
-    }
-
-    HttpEngine getHttpEngine() {
-        return delegate.getHttpEngine();
-    }
-
-    @Override
-    public String getCipherSuite() {
-        SecureCacheResponse cacheResponse = delegate.getCacheResponse();
-        if (cacheResponse != null) {
-            return cacheResponse.getCipherSuite();
-        }
-        checkConnected();
-        return delegate.getSSLSocket().getSession().getCipherSuite();
-    }
-
-    @Override
-    public Certificate[] getLocalCertificates() {
-        SecureCacheResponse cacheResponse = delegate.getCacheResponse();
-        if (cacheResponse != null) {
-            List<Certificate> result = cacheResponse.getLocalCertificateChain();
-            return result != null ? result.toArray(new Certificate[result.size()]) : null;
-        }
-        checkConnected();
-        return delegate.getSSLSocket().getSession().getLocalCertificates();
-    }
-
-    @Override
-    public Certificate[] getServerCertificates() throws SSLPeerUnverifiedException {
-        SecureCacheResponse cacheResponse = delegate.getCacheResponse();
-        if (cacheResponse != null) {
-            List<Certificate> result = cacheResponse.getServerCertificateChain();
-            return result != null ? result.toArray(new Certificate[result.size()]) : null;
-        }
-        checkConnected();
-        return delegate.getSSLSocket().getSession().getPeerCertificates();
-    }
-
-    @Override
-    public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
-        SecureCacheResponse cacheResponse = delegate.getCacheResponse();
-        if (cacheResponse != null) {
-            return cacheResponse.getPeerPrincipal();
-        }
-        checkConnected();
-        return delegate.getSSLSocket().getSession().getPeerPrincipal();
-    }
-
-    @Override
-    public Principal getLocalPrincipal() {
-        SecureCacheResponse cacheResponse = delegate.getCacheResponse();
-        if (cacheResponse != null) {
-            return cacheResponse.getLocalPrincipal();
-        }
-        checkConnected();
-        return delegate.getSSLSocket().getSession().getLocalPrincipal();
-    }
-
-    @Override
-    public void disconnect() {
-        delegate.disconnect();
-    }
-
-    @Override
-    public InputStream getErrorStream() {
-        return delegate.getErrorStream();
-    }
-
-    @Override
-    public String getRequestMethod() {
-        return delegate.getRequestMethod();
-    }
-
-    @Override
-    public int getResponseCode() throws IOException {
-        return delegate.getResponseCode();
-    }
-
-    @Override
-    public String getResponseMessage() throws IOException {
-        return delegate.getResponseMessage();
-    }
-
-    @Override
-    public void setRequestMethod(String method) throws ProtocolException {
-        delegate.setRequestMethod(method);
-    }
-
-    @Override
-    public boolean usingProxy() {
-        return delegate.usingProxy();
-    }
-
-    @Override
-    public boolean getInstanceFollowRedirects() {
-        return delegate.getInstanceFollowRedirects();
-    }
-
-    @Override
-    public void setInstanceFollowRedirects(boolean followRedirects) {
-        delegate.setInstanceFollowRedirects(followRedirects);
-    }
-
-    @Override
-    public void connect() throws IOException {
-        connected = true;
-        delegate.connect();
-    }
-
-    @Override
-    public boolean getAllowUserInteraction() {
-        return delegate.getAllowUserInteraction();
-    }
-
-    @Override
-    public Object getContent() throws IOException {
-        return delegate.getContent();
-    }
-
-    @SuppressWarnings("unchecked") // Spec does not generify
-    @Override
-    public Object getContent(Class[] types) throws IOException {
-        return delegate.getContent(types);
-    }
-
-    @Override
-    public String getContentEncoding() {
-        return delegate.getContentEncoding();
-    }
-
-    @Override
-    public int getContentLength() {
-        return delegate.getContentLength();
-    }
-
-    @Override
-    public String getContentType() {
-        return delegate.getContentType();
-    }
-
-    @Override
-    public long getDate() {
-        return delegate.getDate();
-    }
-
-    @Override
-    public boolean getDefaultUseCaches() {
-        return delegate.getDefaultUseCaches();
-    }
-
-    @Override
-    public boolean getDoInput() {
-        return delegate.getDoInput();
-    }
-
-    @Override
-    public boolean getDoOutput() {
-        return delegate.getDoOutput();
-    }
-
-    @Override
-    public long getExpiration() {
-        return delegate.getExpiration();
-    }
-
-    @Override
-    public String getHeaderField(int pos) {
-        return delegate.getHeaderField(pos);
-    }
-
-    @Override
-    public Map<String, List<String>> getHeaderFields() {
-        return delegate.getHeaderFields();
-    }
-
-    @Override
-    public Map<String, List<String>> getRequestProperties() {
-        return delegate.getRequestProperties();
-    }
-
-    @Override
-    public void addRequestProperty(String field, String newValue) {
-        delegate.addRequestProperty(field, newValue);
-    }
-
-    @Override
-    public String getHeaderField(String key) {
-        return delegate.getHeaderField(key);
-    }
-
-    @Override
-    public long getHeaderFieldDate(String field, long defaultValue) {
-        return delegate.getHeaderFieldDate(field, defaultValue);
-    }
-
-    @Override
-    public int getHeaderFieldInt(String field, int defaultValue) {
-        return delegate.getHeaderFieldInt(field, defaultValue);
-    }
-
-    @Override
-    public String getHeaderFieldKey(int posn) {
-        return delegate.getHeaderFieldKey(posn);
-    }
-
-    @Override
-    public long getIfModifiedSince() {
-        return delegate.getIfModifiedSince();
-    }
-
-    @Override
-    public InputStream getInputStream() throws IOException {
-        return delegate.getInputStream();
-    }
-
-    @Override
-    public long getLastModified() {
-        return delegate.getLastModified();
-    }
-
-    @Override
-    public OutputStream getOutputStream() throws IOException {
-        return delegate.getOutputStream();
-    }
-
-    @Override
-    public Permission getPermission() throws IOException {
-        return delegate.getPermission();
-    }
-
-    @Override
-    public String getRequestProperty(String field) {
-        return delegate.getRequestProperty(field);
-    }
-
-    @Override
-    public URL getURL() {
-        return delegate.getURL();
-    }
-
-    @Override
-    public boolean getUseCaches() {
-        return delegate.getUseCaches();
-    }
-
-    @Override
-    public void setAllowUserInteraction(boolean newValue) {
-        delegate.setAllowUserInteraction(newValue);
-    }
-
-    @Override
-    public void setDefaultUseCaches(boolean newValue) {
-        delegate.setDefaultUseCaches(newValue);
-    }
-
-    @Override
-    public void setDoInput(boolean newValue) {
-        delegate.setDoInput(newValue);
-    }
-
-    @Override
-    public void setDoOutput(boolean newValue) {
-        delegate.setDoOutput(newValue);
-    }
-
-    @Override
-    public void setIfModifiedSince(long newValue) {
-        delegate.setIfModifiedSince(newValue);
-    }
-
-    @Override
-    public void setRequestProperty(String field, String newValue) {
-        delegate.setRequestProperty(field, newValue);
-    }
-
-    @Override
-    public void setUseCaches(boolean newValue) {
-        delegate.setUseCaches(newValue);
-    }
-
-    @Override
-    public void setConnectTimeout(int timeoutMillis) {
-        delegate.setConnectTimeout(timeoutMillis);
-    }
-
-    @Override
-    public int getConnectTimeout() {
-        return delegate.getConnectTimeout();
-    }
-
-    @Override
-    public void setReadTimeout(int timeoutMillis) {
-        delegate.setReadTimeout(timeoutMillis);
-    }
-
-    @Override
-    public int getReadTimeout() {
-        return delegate.getReadTimeout();
-    }
-
-    @Override
-    public String toString() {
-        return delegate.toString();
-    }
-
-    @Override
-    public void setFixedLengthStreamingMode(int contentLength) {
-        delegate.setFixedLengthStreamingMode(contentLength);
-    }
-
-    @Override
-    public void setChunkedStreamingMode(int chunkLength) {
-        delegate.setChunkedStreamingMode(chunkLength);
-    }
-
-    private final class HttpUrlConnectionDelegate extends HttpURLConnectionImpl {
-        private HttpUrlConnectionDelegate(URL url, int port) {
-            super(url, port);
-        }
-
-        private HttpUrlConnectionDelegate(URL url, int port, Proxy proxy) {
-            super(url, port, proxy);
-        }
-
-        @Override protected HttpEngine newHttpEngine(String method, RawHeaders requestHeaders,
-                HttpConnection connection, RetryableOutputStream requestBody) throws IOException {
-            return new HttpsEngine(this, method, requestHeaders, connection, requestBody,
-                    HttpsURLConnectionImpl.this);
-        }
-
-        public SecureCacheResponse getCacheResponse() {
-            HttpsEngine engine = (HttpsEngine) httpEngine;
-            return engine != null ? (SecureCacheResponse) engine.getCacheResponse() : null;
-        }
-
-        public SSLSocket getSSLSocket() {
-            HttpsEngine engine = (HttpsEngine) httpEngine;
-            return engine != null ? engine.sslSocket : null;
-        }
-    }
-
-    private static class HttpsEngine extends HttpEngine {
-
-        /**
-         * Local stash of HttpsEngine.connection.sslSocket for answering
-         * queries such as getCipherSuite even after
-         * httpsEngine.Connection has been recycled. It's presence is also
-         * used to tell if the HttpsURLConnection is considered connected,
-         * as opposed to the connected field of URLConnection or the a
-         * non-null connect in HttpURLConnectionImpl
-         */
-        private SSLSocket sslSocket;
-
-        private final HttpsURLConnectionImpl enclosing;
-
-        /**
-         * @param policy the HttpURLConnectionImpl with connection configuration
-         * @param enclosing the HttpsURLConnection with HTTPS features
-         */
-        private HttpsEngine(HttpURLConnectionImpl policy, String method, RawHeaders requestHeaders,
-                HttpConnection connection, RetryableOutputStream requestBody,
-                HttpsURLConnectionImpl enclosing) throws IOException {
-            super(policy, method, requestHeaders, connection, requestBody);
-            this.sslSocket = connection != null ? connection.getSecureSocketIfConnected() : null;
-            this.enclosing = enclosing;
-        }
-
-        @Override protected void connect() throws IOException {
-            // first try an SSL connection with compression and
-            // various TLS extensions enabled, if it fails (and its
-            // not unheard of that it will) fallback to a more
-            // barebones connections
-            boolean connectionReused;
-            try {
-                connectionReused = makeSslConnection(true);
-            } catch (IOException e) {
-                // If the problem was a CertificateException from the X509TrustManager,
-                // do not retry, we didn't have an abrupt server initiated exception.
-                if (e instanceof SSLHandshakeException
-                        && e.getCause() instanceof CertificateException) {
-                    throw e;
-                }
-                release(false);
-                connectionReused = makeSslConnection(false);
-            }
-
-            if (!connectionReused) {
-                sslSocket = connection.verifySecureSocketHostname(enclosing.getHostnameVerifier());
-            }
-        }
-
-        /**
-         * Attempt to make an https connection. Returns true if a
-         * connection was reused, false otherwise.
-         *
-         * @param tlsTolerant If true, assume server can handle common
-         * TLS extensions and SSL deflate compression. If false, use
-         * an SSL3 only fallback mode without compression.
-         */
-        private boolean makeSslConnection(boolean tlsTolerant) throws IOException {
-            // make an SSL Tunnel on the first message pair of each SSL + proxy connection
-            if (connection == null) {
-                connection = openSocketConnection();
-                if (connection.getAddress().getProxy() != null) {
-                    makeTunnel(policy, connection, getRequestHeaders());
-                }
-            }
-
-            // if super.makeConnection returned a connection from the
-            // pool, sslSocket needs to be initialized here. If it is
-            // a new connection, it will be initialized by
-            // getSecureSocket below.
-            sslSocket = connection.getSecureSocketIfConnected();
-
-            // we already have an SSL connection,
-            if (sslSocket != null) {
-                return true;
-            }
-
-            connection.setupSecureSocket(enclosing.getSSLSocketFactory(), tlsTolerant);
-            return false;
-        }
-
-        /**
-         * To make an HTTPS connection over an HTTP proxy, send an unencrypted
-         * CONNECT request to create the proxy connection. This may need to be
-         * retried if the proxy requires authorization.
-         */
-        private void makeTunnel(HttpURLConnectionImpl policy, HttpConnection connection,
-                RequestHeaders requestHeaders) throws IOException {
-            RawHeaders rawRequestHeaders = requestHeaders.getHeaders();
-            while (true) {
-                HttpEngine connect = new ProxyConnectEngine(policy, rawRequestHeaders, connection);
-                connect.sendRequest();
-                connect.readResponse();
-
-                int responseCode = connect.getResponseCode();
-                switch (connect.getResponseCode()) {
-                case HTTP_OK:
-                    return;
-                case HTTP_PROXY_AUTH:
-                    rawRequestHeaders = new RawHeaders(rawRequestHeaders);
-                    boolean credentialsFound = policy.processAuthHeader(HTTP_PROXY_AUTH,
-                            connect.getResponseHeaders(), rawRequestHeaders);
-                    if (credentialsFound) {
-                        continue;
-                    } else {
-                        throw new IOException("Failed to authenticate with proxy");
-                    }
-                default:
-                    throw new IOException("Unexpected response code for CONNECT: " + responseCode);
-                }
-            }
-        }
-
-        @Override protected boolean acceptCacheResponseType(CacheResponse cacheResponse) {
-            return cacheResponse instanceof SecureCacheResponse;
-        }
-
-        @Override protected boolean includeAuthorityInRequestLine() {
-            // Even if there is a proxy, it isn't involved. Always request just the file.
-            return false;
-        }
-
-        @Override protected SSLSocketFactory getSslSocketFactory() {
-            return enclosing.getSSLSocketFactory();
-        }
-
-        @Override protected HttpURLConnection getHttpConnectionToCache() {
-            return enclosing;
-        }
-    }
-
-    private static class ProxyConnectEngine extends HttpEngine {
-        public ProxyConnectEngine(HttpURLConnectionImpl policy, RawHeaders requestHeaders,
-                HttpConnection connection) throws IOException {
-            super(policy, HttpEngine.CONNECT, requestHeaders, connection, null);
-        }
-
-        /**
-         * If we're establishing an HTTPS tunnel with CONNECT (RFC 2817 5.2), send
-         * only the minimum set of headers. This avoids sending potentially
-         * sensitive data like HTTP cookies to the proxy unencrypted.
-         */
-        @Override protected RawHeaders getNetworkRequestHeaders() throws IOException {
-            RequestHeaders privateHeaders = getRequestHeaders();
-            URL url = policy.getURL();
-
-            RawHeaders result = new RawHeaders();
-            result.setStatusLine("CONNECT " + url.getHost() + ":" + url.getEffectivePort()
-                    + " HTTP/1.1");
-
-            // Always set Host and User-Agent.
-            String host = privateHeaders.getHost();
-            if (host == null) {
-                host = getOriginAddress(url);
-            }
-            result.set("Host", host);
-
-            String userAgent = privateHeaders.getUserAgent();
-            if (userAgent == null) {
-                userAgent = getDefaultUserAgent();
-            }
-            result.set("User-Agent", userAgent);
-
-            // Copy over the Proxy-Authorization header if it exists.
-            String proxyAuthorization = privateHeaders.getProxyAuthorization();
-            if (proxyAuthorization != null) {
-                result.set("Proxy-Authorization", proxyAuthorization);
-            }
-
-            // Always set the Proxy-Connection to Keep-Alive for the benefit of
-            // HTTP/1.0 proxies like Squid.
-            result.set("Proxy-Connection", "Keep-Alive");
-            return result;
-        }
-
-        @Override protected boolean requiresTunnel() {
-            return true;
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/RawHeaders.java b/luni/src/main/java/libcore/net/http/RawHeaders.java
deleted file mode 100644
index 21b48f1..0000000
--- a/luni/src/main/java/libcore/net/http/RawHeaders.java
+++ /dev/null
@@ -1,297 +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 libcore.net.http;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-
-/**
- * The HTTP status and unparsed header fields of a single HTTP message. Values
- * are represented as uninterpreted strings; use {@link RequestHeaders} and
- * {@link ResponseHeaders} for interpreted headers. This class maintains the
- * order of the header fields within the HTTP message.
- *
- * <p>This class tracks fields line-by-line. A field with multiple comma-
- * separated values on the same line will be treated as a field with a single
- * value by this class. It is the caller's responsibility to detect and split
- * on commas if their field permits multiple values. This simplifies use of
- * single-valued fields whose values routinely contain commas, such as cookies
- * or dates.
- *
- * <p>This class trims whitespace from values. It never returns values with
- * leading or trailing whitespace.
- */
-public final class RawHeaders {
-    private static final Comparator<String> FIELD_NAME_COMPARATOR = new Comparator<String>() {
-        @FindBugsSuppressWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ")
-        @Override public int compare(String a, String b) {
-            if (a == b) {
-                return 0;
-            } else if (a == null) {
-                return -1;
-            } else if (b == null) {
-                return 1;
-            } else {
-                return String.CASE_INSENSITIVE_ORDER.compare(a, b);
-            }
-        }
-    };
-
-    private final List<String> namesAndValues = new ArrayList<String>(20);
-    private String statusLine;
-    private int httpMinorVersion = 1;
-    private int responseCode = -1;
-    private String responseMessage;
-
-    public RawHeaders() {}
-
-    public RawHeaders(RawHeaders copyFrom) {
-        namesAndValues.addAll(copyFrom.namesAndValues);
-        statusLine = copyFrom.statusLine;
-        httpMinorVersion = copyFrom.httpMinorVersion;
-        responseCode = copyFrom.responseCode;
-        responseMessage = copyFrom.responseMessage;
-    }
-
-    /**
-     * Sets the response status line (like "HTTP/1.0 200 OK") or request line
-     * (like "GET / HTTP/1.1").
-     */
-    public void setStatusLine(String statusLine) {
-        statusLine = statusLine.trim();
-        this.statusLine = statusLine;
-
-        if (statusLine == null || !statusLine.startsWith("HTTP/")) {
-            return;
-        }
-        statusLine = statusLine.trim();
-        int mark = statusLine.indexOf(" ") + 1;
-        if (mark == 0) {
-            return;
-        }
-        if (statusLine.charAt(mark - 2) != '1') {
-            this.httpMinorVersion = 0;
-        }
-        int last = mark + 3;
-        if (last > statusLine.length()) {
-            last = statusLine.length();
-        }
-        this.responseCode = Integer.parseInt(statusLine.substring(mark, last));
-        if (last + 1 <= statusLine.length()) {
-            this.responseMessage = statusLine.substring(last + 1);
-        }
-    }
-
-    public String getStatusLine() {
-        return statusLine;
-    }
-
-    /**
-     * Returns the status line's HTTP minor version. This returns 0 for HTTP/1.0
-     * and 1 for HTTP/1.1. This returns 1 if the HTTP version is unknown.
-     */
-    public int getHttpMinorVersion() {
-        return httpMinorVersion != -1 ? httpMinorVersion : 1;
-    }
-
-    /**
-     * Returns the HTTP status code or -1 if it is unknown.
-     */
-    public int getResponseCode() {
-        return responseCode;
-    }
-
-    /**
-     * Returns the HTTP status message or null if it is unknown.
-     */
-    public String getResponseMessage() {
-        return responseMessage;
-    }
-
-    /**
-     * Add an HTTP header line containing a field name, a literal colon, and a
-     * value.
-     */
-    public void addLine(String line) {
-        int index = line.indexOf(":");
-        if (index == -1) {
-            add("", line);
-        } else {
-            add(line.substring(0, index), line.substring(index + 1));
-        }
-    }
-
-    /**
-     * Add a field with the specified value.
-     */
-    public void add(String fieldName, String value) {
-        if (fieldName == null) {
-            throw new IllegalArgumentException("fieldName == null");
-        }
-        if (value == null) {
-            /*
-             * Given null values, the RI sends a malformed field line like
-             * "Accept\r\n". For platform compatibility and HTTP compliance, we
-             * print a warning and ignore null values.
-             */
-            System.logW("Ignoring HTTP header field '" + fieldName + "' because its value is null");
-            return;
-        }
-        namesAndValues.add(fieldName);
-        namesAndValues.add(value.trim());
-    }
-
-    public void removeAll(String fieldName) {
-        for (int i = 0; i < namesAndValues.size(); i += 2) {
-            if (fieldName.equalsIgnoreCase(namesAndValues.get(i))) {
-                namesAndValues.remove(i); // field name
-                namesAndValues.remove(i); // value
-            }
-        }
-    }
-
-    public void addAll(String fieldName, List<String> headerFields) {
-        for (String value : headerFields) {
-            add(fieldName, value);
-        }
-    }
-
-    /**
-     * Set a field with the specified value. If the field is not found, it is
-     * added. If the field is found, the existing values are replaced.
-     */
-    public void set(String fieldName, String value) {
-        removeAll(fieldName);
-        add(fieldName, value);
-    }
-
-    /**
-     * Returns the number of field values.
-     */
-    public int length() {
-        return namesAndValues.size() / 2;
-    }
-
-    /**
-     * Returns the field at {@code position} or null if that is out of range.
-     */
-    public String getFieldName(int index) {
-        int fieldNameIndex = index * 2;
-        if (fieldNameIndex < 0 || fieldNameIndex >= namesAndValues.size()) {
-            return null;
-        }
-        return namesAndValues.get(fieldNameIndex);
-    }
-
-    /**
-     * Returns the value at {@code index} or null if that is out of range.
-     */
-    public String getValue(int index) {
-        int valueIndex = index * 2 + 1;
-        if (valueIndex < 0 || valueIndex >= namesAndValues.size()) {
-            return null;
-        }
-        return namesAndValues.get(valueIndex);
-    }
-
-    /**
-     * Returns the last value corresponding to the specified field, or null.
-     */
-    public String get(String fieldName) {
-        for (int i = namesAndValues.size() - 2; i >= 0; i -= 2) {
-            if (fieldName.equalsIgnoreCase(namesAndValues.get(i))) {
-                return namesAndValues.get(i + 1);
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @param fieldNames a case-insensitive set of HTTP header field names.
-     */
-    public RawHeaders getAll(Set<String> fieldNames) {
-        RawHeaders result = new RawHeaders();
-        for (int i = 0; i < namesAndValues.size(); i += 2) {
-            String fieldName = namesAndValues.get(i);
-            if (fieldNames.contains(fieldName)) {
-                result.add(fieldName, namesAndValues.get(i + 1));
-            }
-        }
-        return result;
-    }
-
-    public String toHeaderString() {
-        StringBuilder result = new StringBuilder(256);
-        result.append(statusLine).append("\r\n");
-        for (int i = 0; i < namesAndValues.size(); i += 2) {
-            result.append(namesAndValues.get(i)).append(": ")
-                    .append(namesAndValues.get(i + 1)).append("\r\n");
-        }
-        result.append("\r\n");
-        return result.toString();
-    }
-
-    /**
-     * Returns an immutable map containing each field to its list of values. The
-     * status line is mapped to null.
-     */
-    public Map<String, List<String>> toMultimap() {
-        Map<String, List<String>> result = new TreeMap<String, List<String>>(FIELD_NAME_COMPARATOR);
-        for (int i = 0; i < namesAndValues.size(); i += 2) {
-            String fieldName = namesAndValues.get(i);
-            String value = namesAndValues.get(i + 1);
-
-            List<String> allValues = new ArrayList<String>();
-            List<String> otherValues = result.get(fieldName);
-            if (otherValues != null) {
-                allValues.addAll(otherValues);
-            }
-            allValues.add(value);
-            result.put(fieldName, Collections.unmodifiableList(allValues));
-        }
-        if (statusLine != null) {
-            result.put(null, Collections.unmodifiableList(Collections.singletonList(statusLine)));
-        }
-        return Collections.unmodifiableMap(result);
-    }
-
-    /**
-     * Creates a new instance from the given map of fields to values. If
-     * present, the null field's last element will be used to set the status
-     * line.
-     */
-    public static RawHeaders fromMultimap(Map<String, List<String>> map) {
-        RawHeaders result = new RawHeaders();
-        for (Entry<String, List<String>> entry : map.entrySet()) {
-            String fieldName = entry.getKey();
-            List<String> values = entry.getValue();
-            if (fieldName != null) {
-                result.addAll(fieldName, values);
-            } else if (!values.isEmpty()) {
-                result.setStatusLine(values.get(values.size() - 1));
-            }
-        }
-        return result;
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/RequestHeaders.java b/luni/src/main/java/libcore/net/http/RequestHeaders.java
deleted file mode 100644
index 3b536ce..0000000
--- a/luni/src/main/java/libcore/net/http/RequestHeaders.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.net.URI;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Parsed HTTP request headers.
- */
-public final class RequestHeaders {
-    private final URI uri;
-    private final RawHeaders headers;
-
-    /** Don't use a cache to satisfy this request. */
-    private boolean noCache;
-    private int maxAgeSeconds = -1;
-    private int maxStaleSeconds = -1;
-    private int minFreshSeconds = -1;
-
-    /**
-     * This field's name "only-if-cached" is misleading. It actually means "do
-     * not use the network". It is set by a client who only wants to make a
-     * request if it can be fully satisfied by the cache. Cached responses that
-     * would require validation (ie. conditional gets) are not permitted if this
-     * header is set.
-     */
-    private boolean onlyIfCached;
-
-    /**
-     * True if the request contains an authorization field. Although this isn't
-     * necessarily a shared cache, it follows the spec's strict requirements for
-     * shared caches.
-     */
-    private boolean hasAuthorization;
-
-    private int contentLength = -1;
-    private String transferEncoding;
-    private String userAgent;
-    private String host;
-    private String connection;
-    private String acceptEncoding;
-    private String contentType;
-    private String ifModifiedSince;
-    private String ifNoneMatch;
-    private String proxyAuthorization;
-
-    public RequestHeaders(URI uri, RawHeaders headers) {
-        this.uri = uri;
-        this.headers = headers;
-
-        HeaderParser.CacheControlHandler handler = new HeaderParser.CacheControlHandler() {
-            @Override public void handle(String directive, String parameter) {
-                if (directive.equalsIgnoreCase("no-cache")) {
-                    noCache = true;
-                } else if (directive.equalsIgnoreCase("max-age")) {
-                    maxAgeSeconds = HeaderParser.parseSeconds(parameter);
-                } else if (directive.equalsIgnoreCase("max-stale")) {
-                    maxStaleSeconds = HeaderParser.parseSeconds(parameter);
-                } else if (directive.equalsIgnoreCase("min-fresh")) {
-                    minFreshSeconds = HeaderParser.parseSeconds(parameter);
-                } else if (directive.equalsIgnoreCase("only-if-cached")) {
-                    onlyIfCached = true;
-                }
-            }
-        };
-
-        for (int i = 0; i < headers.length(); i++) {
-            String fieldName = headers.getFieldName(i);
-            String value = headers.getValue(i);
-            if ("Cache-Control".equalsIgnoreCase(fieldName)) {
-                HeaderParser.parseCacheControl(value, handler);
-            } else if ("Pragma".equalsIgnoreCase(fieldName)) {
-                if (value.equalsIgnoreCase("no-cache")) {
-                    noCache = true;
-                }
-            } else if ("If-None-Match".equalsIgnoreCase(fieldName)) {
-                ifNoneMatch = value;
-            } else if ("If-Modified-Since".equalsIgnoreCase(fieldName)) {
-                ifModifiedSince = value;
-            } else if ("Authorization".equalsIgnoreCase(fieldName)) {
-                hasAuthorization = true;
-            } else if ("Content-Length".equalsIgnoreCase(fieldName)) {
-                try {
-                    contentLength = Integer.parseInt(value);
-                } catch (NumberFormatException ignored) {
-                }
-            } else if ("Transfer-Encoding".equalsIgnoreCase(fieldName)) {
-                transferEncoding = value;
-            } else if ("User-Agent".equalsIgnoreCase(fieldName)) {
-                userAgent = value;
-            } else if ("Host".equalsIgnoreCase(fieldName)) {
-                host = value;
-            } else if ("Connection".equalsIgnoreCase(fieldName)) {
-                connection = value;
-            } else if ("Accept-Encoding".equalsIgnoreCase(fieldName)) {
-                acceptEncoding = value;
-            } else if ("Content-Type".equalsIgnoreCase(fieldName)) {
-                contentType = value;
-            } else if ("Proxy-Authorization".equalsIgnoreCase(fieldName)) {
-                proxyAuthorization = value;
-            }
-        }
-    }
-
-    public boolean isChunked() {
-        return "chunked".equalsIgnoreCase(transferEncoding);
-    }
-
-    public boolean hasConnectionClose() {
-        return "close".equalsIgnoreCase(connection);
-    }
-
-    public URI getUri() {
-        return uri;
-    }
-
-    public RawHeaders getHeaders() {
-        return headers;
-    }
-
-    public boolean isNoCache() {
-        return noCache;
-    }
-
-    public int getMaxAgeSeconds() {
-        return maxAgeSeconds;
-    }
-
-    public int getMaxStaleSeconds() {
-        return maxStaleSeconds;
-    }
-
-    public int getMinFreshSeconds() {
-        return minFreshSeconds;
-    }
-
-    public boolean isOnlyIfCached() {
-        return onlyIfCached;
-    }
-
-    public boolean hasAuthorization() {
-        return hasAuthorization;
-    }
-
-    public int getContentLength() {
-        return contentLength;
-    }
-
-    public String getTransferEncoding() {
-        return transferEncoding;
-    }
-
-    public String getUserAgent() {
-        return userAgent;
-    }
-
-    public String getHost() {
-        return host;
-    }
-
-    public String getConnection() {
-        return connection;
-    }
-
-    public String getAcceptEncoding() {
-        return acceptEncoding;
-    }
-
-    public String getContentType() {
-        return contentType;
-    }
-
-    public String getIfModifiedSince() {
-        return ifModifiedSince;
-    }
-
-    public String getIfNoneMatch() {
-        return ifNoneMatch;
-    }
-
-    public String getProxyAuthorization() {
-        return proxyAuthorization;
-    }
-
-    public void setChunked() {
-        if (this.transferEncoding != null) {
-            headers.removeAll("Transfer-Encoding");
-        }
-        headers.add("Transfer-Encoding", "chunked");
-        this.transferEncoding = "chunked";
-    }
-
-    public void setContentLength(int contentLength) {
-        if (this.contentLength != -1) {
-            headers.removeAll("Content-Length");
-        }
-        headers.add("Content-Length", Integer.toString(contentLength));
-        this.contentLength = contentLength;
-    }
-
-    public void setUserAgent(String userAgent) {
-        if (this.userAgent != null) {
-            headers.removeAll("User-Agent");
-        }
-        headers.add("User-Agent", userAgent);
-        this.userAgent = userAgent;
-    }
-
-    public void setHost(String host) {
-        if (this.host != null) {
-            headers.removeAll("Host");
-        }
-        headers.add("Host", host);
-        this.host = host;
-    }
-
-    public void setConnection(String connection) {
-        if (this.connection != null) {
-            headers.removeAll("Connection");
-        }
-        headers.add("Connection", connection);
-        this.connection = connection;
-    }
-
-    public void setAcceptEncoding(String acceptEncoding) {
-        if (this.acceptEncoding != null) {
-            headers.removeAll("Accept-Encoding");
-        }
-        headers.add("Accept-Encoding", acceptEncoding);
-        this.acceptEncoding = acceptEncoding;
-    }
-
-    public void setContentType(String contentType) {
-        if (this.contentType != null) {
-            headers.removeAll("Content-Type");
-        }
-        headers.add("Content-Type", contentType);
-        this.contentType = contentType;
-    }
-
-    public void setIfModifiedSince(Date date) {
-        if (ifModifiedSince != null) {
-            headers.removeAll("If-Modified-Since");
-        }
-        String formattedDate = HttpDate.format(date);
-        headers.add("If-Modified-Since", formattedDate);
-        ifModifiedSince = formattedDate;
-    }
-
-    public void setIfNoneMatch(String ifNoneMatch) {
-        if (this.ifNoneMatch != null) {
-            headers.removeAll("If-None-Match");
-        }
-        headers.add("If-None-Match", ifNoneMatch);
-        this.ifNoneMatch = ifNoneMatch;
-    }
-
-    /**
-     * Returns true if the request contains conditions that save the server from
-     * sending a response that the client has locally. When the caller adds
-     * conditions, this cache won't participate in the request.
-     */
-    public boolean hasConditions() {
-        return ifModifiedSince != null || ifNoneMatch != null;
-    }
-
-    public void addCookies(Map<String, List<String>> allCookieHeaders) {
-        for (Map.Entry<String, List<String>> entry : allCookieHeaders.entrySet()) {
-            String key = entry.getKey();
-            if ("Cookie".equalsIgnoreCase(key) || "Cookie2".equalsIgnoreCase(key)) {
-                headers.addAll(key, entry.getValue());
-            }
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/ResponseHeaders.java b/luni/src/main/java/libcore/net/http/ResponseHeaders.java
deleted file mode 100644
index c0b4200..0000000
--- a/luni/src/main/java/libcore/net/http/ResponseHeaders.java
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import java.net.HttpURLConnection;
-import java.net.ResponseSource;
-import java.net.URI;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.TimeUnit;
-import libcore.util.Objects;
-
-/**
- * Parsed HTTP response headers.
- */
-public final class ResponseHeaders {
-
-    /** HTTP header name for the local time when the request was sent. */
-    private static final String SENT_MILLIS = "X-Android-Sent-Millis";
-
-    /** HTTP header name for the local time when the response was received. */
-    private static final String RECEIVED_MILLIS = "X-Android-Received-Millis";
-
-    private final URI uri;
-    private final RawHeaders headers;
-
-    /** The server's time when this response was served, if known. */
-    private Date servedDate;
-
-    /** The last modified date of the response, if known. */
-    private Date lastModified;
-
-    /**
-     * The expiration date of the response, if known. If both this field and the
-     * max age are set, the max age is preferred.
-     */
-    private Date expires;
-
-    /**
-     * Extension header set by HttpURLConnectionImpl specifying the timestamp
-     * when the HTTP request was first initiated.
-     */
-    private long sentRequestMillis;
-
-    /**
-     * Extension header set by HttpURLConnectionImpl specifying the timestamp
-     * when the HTTP response was first received.
-     */
-    private long receivedResponseMillis;
-
-    /**
-     * In the response, this field's name "no-cache" is misleading. It doesn't
-     * prevent us from caching the response; it only means we have to validate
-     * the response with the origin server before returning it. We can do this
-     * with a conditional get.
-     */
-    private boolean noCache;
-
-    /** If true, this response should not be cached. */
-    private boolean noStore;
-
-    /**
-     * The duration past the response's served date that it can be served
-     * without validation.
-     */
-    private int maxAgeSeconds = -1;
-
-    /**
-     * The "s-maxage" directive is the max age for shared caches. Not to be
-     * confused with "max-age" for non-shared caches, As in Firefox and Chrome,
-     * this directive is not honored by this cache.
-     */
-    private int sMaxAgeSeconds = -1;
-
-    /**
-     * This request header field's name "only-if-cached" is misleading. It
-     * actually means "do not use the network". It is set by a client who only
-     * wants to make a request if it can be fully satisfied by the cache.
-     * Cached responses that would require validation (ie. conditional gets) are
-     * not permitted if this header is set.
-     */
-    private boolean isPublic;
-    private boolean mustRevalidate;
-    private String etag;
-    private int ageSeconds = -1;
-
-    /** Case-insensitive set of field names. */
-    private Set<String> varyFields = Collections.emptySet();
-
-    private String contentEncoding;
-    private String transferEncoding;
-    private int contentLength = -1;
-    private String connection;
-
-    public ResponseHeaders(URI uri, RawHeaders headers) {
-        this.uri = uri;
-        this.headers = headers;
-
-        HeaderParser.CacheControlHandler handler = new HeaderParser.CacheControlHandler() {
-            @Override public void handle(String directive, String parameter) {
-                if (directive.equalsIgnoreCase("no-cache")) {
-                    noCache = true;
-                } else if (directive.equalsIgnoreCase("no-store")) {
-                    noStore = true;
-                } else if (directive.equalsIgnoreCase("max-age")) {
-                    maxAgeSeconds = HeaderParser.parseSeconds(parameter);
-                } else if (directive.equalsIgnoreCase("s-maxage")) {
-                    sMaxAgeSeconds = HeaderParser.parseSeconds(parameter);
-                } else if (directive.equalsIgnoreCase("public")) {
-                    isPublic = true;
-                } else if (directive.equalsIgnoreCase("must-revalidate")) {
-                    mustRevalidate = true;
-                }
-            }
-        };
-
-        for (int i = 0; i < headers.length(); i++) {
-            String fieldName = headers.getFieldName(i);
-            String value = headers.getValue(i);
-            if ("Cache-Control".equalsIgnoreCase(fieldName)) {
-                HeaderParser.parseCacheControl(value, handler);
-            } else if ("Date".equalsIgnoreCase(fieldName)) {
-                servedDate = HttpDate.parse(value);
-            } else if ("Expires".equalsIgnoreCase(fieldName)) {
-                expires = HttpDate.parse(value);
-            } else if ("Last-Modified".equalsIgnoreCase(fieldName)) {
-                lastModified = HttpDate.parse(value);
-            } else if ("ETag".equalsIgnoreCase(fieldName)) {
-                etag = value;
-            } else if ("Pragma".equalsIgnoreCase(fieldName)) {
-                if (value.equalsIgnoreCase("no-cache")) {
-                    noCache = true;
-                }
-            } else if ("Age".equalsIgnoreCase(fieldName)) {
-                ageSeconds = HeaderParser.parseSeconds(value);
-            } else if ("Vary".equalsIgnoreCase(fieldName)) {
-                // Replace the immutable empty set with something we can mutate.
-                if (varyFields.isEmpty()) {
-                    varyFields = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
-                }
-                for (String varyField : value.split(",")) {
-                    varyFields.add(varyField.trim());
-                }
-            } else if ("Content-Encoding".equalsIgnoreCase(fieldName)) {
-                contentEncoding = value;
-            } else if ("Transfer-Encoding".equalsIgnoreCase(fieldName)) {
-                transferEncoding = value;
-            } else if ("Content-Length".equalsIgnoreCase(fieldName)) {
-                try {
-                    contentLength = Integer.parseInt(value);
-                } catch (NumberFormatException ignored) {
-                }
-            } else if ("Connection".equalsIgnoreCase(fieldName)) {
-                connection = value;
-            } else if (SENT_MILLIS.equalsIgnoreCase(fieldName)) {
-                sentRequestMillis = Long.parseLong(value);
-            } else if (RECEIVED_MILLIS.equalsIgnoreCase(fieldName)) {
-                receivedResponseMillis = Long.parseLong(value);
-            }
-        }
-    }
-
-    public boolean isContentEncodingGzip() {
-        return "gzip".equalsIgnoreCase(contentEncoding);
-    }
-
-    public void stripContentEncoding() {
-        contentEncoding = null;
-        headers.removeAll("Content-Encoding");
-    }
-
-    public void stripContentLength() {
-        contentLength = -1;
-        headers.removeAll("Content-Length");
-    }
-
-    public boolean isChunked() {
-        return "chunked".equalsIgnoreCase(transferEncoding);
-    }
-
-    public boolean hasConnectionClose() {
-        return "close".equalsIgnoreCase(connection);
-    }
-
-    public URI getUri() {
-        return uri;
-    }
-
-    public RawHeaders getHeaders() {
-        return headers;
-    }
-
-    public Date getServedDate() {
-        return servedDate;
-    }
-
-    public Date getLastModified() {
-        return lastModified;
-    }
-
-    public Date getExpires() {
-        return expires;
-    }
-
-    public boolean isNoCache() {
-        return noCache;
-    }
-
-    public boolean isNoStore() {
-        return noStore;
-    }
-
-    public int getMaxAgeSeconds() {
-        return maxAgeSeconds;
-    }
-
-    public int getSMaxAgeSeconds() {
-        return sMaxAgeSeconds;
-    }
-
-    public boolean isPublic() {
-        return isPublic;
-    }
-
-    public boolean isMustRevalidate() {
-        return mustRevalidate;
-    }
-
-    public String getEtag() {
-        return etag;
-    }
-
-    public Set<String> getVaryFields() {
-        return varyFields;
-    }
-
-    public String getContentEncoding() {
-        return contentEncoding;
-    }
-
-    public int getContentLength() {
-        return contentLength;
-    }
-
-    public String getConnection() {
-        return connection;
-    }
-
-    public void setLocalTimestamps(long sentRequestMillis, long receivedResponseMillis) {
-        this.sentRequestMillis = sentRequestMillis;
-        headers.add(SENT_MILLIS, Long.toString(sentRequestMillis));
-        this.receivedResponseMillis = receivedResponseMillis;
-        headers.add(RECEIVED_MILLIS, Long.toString(receivedResponseMillis));
-    }
-
-    /**
-     * Returns the current age of the response, in milliseconds. The calculation
-     * is specified by RFC 2616, 13.2.3 Age Calculations.
-     */
-    private long computeAge(long nowMillis) {
-        long apparentReceivedAge = servedDate != null
-                ? Math.max(0, receivedResponseMillis - servedDate.getTime())
-                : 0;
-        long receivedAge = ageSeconds != -1
-                ? Math.max(apparentReceivedAge, TimeUnit.SECONDS.toMillis(ageSeconds))
-                : apparentReceivedAge;
-        long responseDuration = receivedResponseMillis - sentRequestMillis;
-        long residentDuration = nowMillis - receivedResponseMillis;
-        return receivedAge + responseDuration + residentDuration;
-    }
-
-    /**
-     * Returns the number of milliseconds that the response was fresh for,
-     * starting from the served date.
-     */
-    private long computeFreshnessLifetime() {
-        if (maxAgeSeconds != -1) {
-            return TimeUnit.SECONDS.toMillis(maxAgeSeconds);
-        } else if (expires != null) {
-            long servedMillis = servedDate != null ? servedDate.getTime() : receivedResponseMillis;
-            long delta = expires.getTime() - servedMillis;
-            return delta > 0 ? delta : 0;
-        } else if (lastModified != null && uri.getRawQuery() == null) {
-            /*
-             * As recommended by the HTTP RFC and implemented in Firefox, the
-             * max age of a document should be defaulted to 10% of the
-             * document's age at the time it was served. Default expiration
-             * dates aren't used for URIs containing a query.
-             */
-            long servedMillis = servedDate != null ? servedDate.getTime() : sentRequestMillis;
-            long delta = servedMillis - lastModified.getTime();
-            return delta > 0 ? (delta / 10) : 0;
-        }
-        return 0;
-    }
-
-    /**
-     * Returns true if computeFreshnessLifetime used a heuristic. If we used a
-     * heuristic to serve a cached response older than 24 hours, we are required
-     * to attach a warning.
-     */
-    private boolean isFreshnessLifetimeHeuristic() {
-        return maxAgeSeconds == -1 && expires == null;
-    }
-
-    /**
-     * Returns true if this response can be stored to later serve another
-     * request.
-     */
-    public boolean isCacheable(RequestHeaders request) {
-        /*
-         * Always go to network for uncacheable response codes (RFC 2616, 13.4),
-         * This implementation doesn't support caching partial content.
-         */
-        int responseCode = headers.getResponseCode();
-        if (responseCode != HttpURLConnection.HTTP_OK
-                && responseCode != HttpURLConnection.HTTP_NOT_AUTHORITATIVE
-                && responseCode != HttpURLConnection.HTTP_MULT_CHOICE
-                && responseCode != HttpURLConnection.HTTP_MOVED_PERM
-                && responseCode != HttpURLConnection.HTTP_GONE) {
-            return false;
-        }
-
-        /*
-         * Responses to authorized requests aren't cacheable unless they include
-         * a 'public', 'must-revalidate' or 's-maxage' directive.
-         */
-        if (request.hasAuthorization()
-                && !isPublic
-                && !mustRevalidate
-                && sMaxAgeSeconds == -1) {
-            return false;
-        }
-
-        if (noStore) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns true if a Vary header contains an asterisk. Such responses cannot
-     * be cached.
-     */
-    public boolean hasVaryAll() {
-        return varyFields.contains("*");
-    }
-
-    /**
-     * Returns true if none of the Vary headers on this response have changed
-     * between {@code cachedRequest} and {@code newRequest}.
-     */
-    public boolean varyMatches(Map<String, List<String>> cachedRequest,
-            Map<String, List<String>> newRequest) {
-        for (String field : varyFields) {
-            if (!Objects.equal(cachedRequest.get(field), newRequest.get(field))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns the source to satisfy {@code request} given this cached response.
-     */
-    public ResponseSource chooseResponseSource(long nowMillis, RequestHeaders request) {
-        /*
-         * If this response shouldn't have been stored, it should never be used
-         * as a response source. This check should be redundant as long as the
-         * persistence store is well-behaved and the rules are constant.
-         */
-        if (!isCacheable(request)) {
-            return ResponseSource.NETWORK;
-        }
-
-        if (request.isNoCache() || request.hasConditions()) {
-            return ResponseSource.NETWORK;
-        }
-
-        long ageMillis = computeAge(nowMillis);
-        long freshMillis = computeFreshnessLifetime();
-
-        if (request.getMaxAgeSeconds() != -1) {
-            freshMillis = Math.min(freshMillis,
-                    TimeUnit.SECONDS.toMillis(request.getMaxAgeSeconds()));
-        }
-
-        long minFreshMillis = 0;
-        if (request.getMinFreshSeconds() != -1) {
-            minFreshMillis = TimeUnit.SECONDS.toMillis(request.getMinFreshSeconds());
-        }
-
-        long maxStaleMillis = 0;
-        if (!mustRevalidate && request.getMaxStaleSeconds() != -1) {
-            maxStaleMillis = TimeUnit.SECONDS.toMillis(request.getMaxStaleSeconds());
-        }
-
-        if (!noCache && ageMillis + minFreshMillis < freshMillis + maxStaleMillis) {
-            if (ageMillis + minFreshMillis >= freshMillis) {
-                headers.add("Warning", "110 HttpURLConnection \"Response is stale\"");
-            }
-            if (ageMillis > TimeUnit.HOURS.toMillis(24) && isFreshnessLifetimeHeuristic()) {
-                headers.add("Warning", "113 HttpURLConnection \"Heuristic expiration\"");
-            }
-            return ResponseSource.CACHE;
-        }
-
-        if (lastModified != null) {
-            request.setIfModifiedSince(lastModified);
-        } else if (servedDate != null) {
-            request.setIfModifiedSince(servedDate);
-        }
-
-        if (etag != null) {
-            request.setIfNoneMatch(etag);
-        }
-
-        return request.hasConditions()
-                ? ResponseSource.CONDITIONAL_CACHE
-                : ResponseSource.NETWORK;
-    }
-
-    /**
-     * Returns true if this cached response should be used; false if the
-     * network response should be used.
-     */
-    public boolean validate(ResponseHeaders networkResponse) {
-        if (networkResponse.headers.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
-            return true;
-        }
-
-        /*
-         * The HTTP spec says that if the network's response is older than our
-         * cached response, we may return the cache's response. Like Chrome (but
-         * unlike Firefox), this client prefers to return the newer response.
-         */
-        if (lastModified != null
-                && networkResponse.lastModified != null
-                && networkResponse.lastModified.getTime() < lastModified.getTime()) {
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     * Combines this cached header with a network header as defined by RFC 2616,
-     * 13.5.3.
-     */
-    public ResponseHeaders combine(ResponseHeaders network) {
-        RawHeaders result = new RawHeaders();
-        result.setStatusLine(headers.getStatusLine());
-
-        for (int i = 0; i < headers.length(); i++) {
-            String fieldName = headers.getFieldName(i);
-            String value = headers.getValue(i);
-            if (fieldName.equals("Warning") && value.startsWith("1")) {
-                continue; // drop 100-level freshness warnings
-            }
-            if (!isEndToEnd(fieldName) || network.headers.get(fieldName) == null) {
-                result.add(fieldName, value);
-            }
-        }
-
-        for (int i = 0; i < network.headers.length(); i++) {
-            String fieldName = network.headers.getFieldName(i);
-            if (isEndToEnd(fieldName)) {
-                result.add(fieldName, network.headers.getValue(i));
-            }
-        }
-
-        return new ResponseHeaders(uri, result);
-    }
-
-    /**
-     * Returns true if {@code fieldName} is an end-to-end HTTP header, as
-     * defined by RFC 2616, 13.5.1.
-     */
-    private static boolean isEndToEnd(String fieldName) {
-        return !fieldName.equalsIgnoreCase("Connection")
-                && !fieldName.equalsIgnoreCase("Keep-Alive")
-                && !fieldName.equalsIgnoreCase("Proxy-Authenticate")
-                && !fieldName.equalsIgnoreCase("Proxy-Authorization")
-                && !fieldName.equalsIgnoreCase("TE")
-                && !fieldName.equalsIgnoreCase("Trailers")
-                && !fieldName.equalsIgnoreCase("Transfer-Encoding")
-                && !fieldName.equalsIgnoreCase("Upgrade");
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/RetryableOutputStream.java b/luni/src/main/java/libcore/net/http/RetryableOutputStream.java
deleted file mode 100644
index 67bb5b8..0000000
--- a/luni/src/main/java/libcore/net/http/RetryableOutputStream.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2010 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.net.http;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * An HTTP request body that's completely buffered in memory. This allows
- * the post body to be transparently re-sent if the HTTP request must be
- * sent multiple times.
- */
-final class RetryableOutputStream extends AbstractHttpOutputStream {
-    private final int limit;
-    private final ByteArrayOutputStream content;
-
-    public RetryableOutputStream(int limit) {
-        this.limit = limit;
-        this.content = new ByteArrayOutputStream(limit);
-    }
-
-    public RetryableOutputStream() {
-        this.limit = -1;
-        this.content = new ByteArrayOutputStream();
-    }
-
-    @Override public synchronized void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        closed = true;
-        if (content.size() < limit) {
-            throw new IOException("content-length promised "
-                    + limit + " bytes, but received " + content.size());
-        }
-    }
-
-    @Override public synchronized void write(byte[] buffer, int offset, int count)
-            throws IOException {
-        checkNotClosed();
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-        if (limit != -1 && content.size() > limit - count) {
-            throw new IOException("exceeded content-length limit of " + limit + " bytes");
-        }
-        content.write(buffer, offset, count);
-    }
-
-    public synchronized int contentLength() throws IOException {
-        close();
-        return content.size();
-    }
-
-    public void writeToSocket(OutputStream socketOut) throws IOException  {
-        content.writeTo(socketOut);
-    }
-}
diff --git a/luni/src/main/java/libcore/net/http/UnknownLengthHttpInputStream.java b/luni/src/main/java/libcore/net/http/UnknownLengthHttpInputStream.java
deleted file mode 100644
index a8224a3..0000000
--- a/luni/src/main/java/libcore/net/http/UnknownLengthHttpInputStream.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010 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.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.CacheRequest;
-import java.util.Arrays;
-
-/**
- * An HTTP payload terminated by the end of the socket stream.
- */
-final class UnknownLengthHttpInputStream extends AbstractHttpInputStream {
-    private boolean inputExhausted;
-
-    UnknownLengthHttpInputStream(InputStream is, CacheRequest cacheRequest,
-            HttpEngine httpEngine) throws IOException {
-        super(is, httpEngine, cacheRequest);
-    }
-
-    @Override public int read(byte[] buffer, int offset, int count) throws IOException {
-        Arrays.checkOffsetAndCount(buffer.length, offset, count);
-        checkNotClosed();
-        if (in == null || inputExhausted) {
-            return -1;
-        }
-        int read = in.read(buffer, offset, count);
-        if (read == -1) {
-            inputExhausted = true;
-            endOfInput(false);
-            return -1;
-        }
-        cacheWrite(buffer, offset, read);
-        return read;
-    }
-
-    @Override public int available() throws IOException {
-        checkNotClosed();
-        return in == null ? 0 : in.available();
-    }
-
-    @Override public void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        closed = true;
-        if (!inputExhausted) {
-            unexpectedEndOfInput();
-        }
-    }
-}
diff --git a/luni/src/main/java/libcore/net/url/FtpURLConnection.java b/luni/src/main/java/libcore/net/url/FtpURLConnection.java
index e168428..7594c3a 100644
--- a/luni/src/main/java/libcore/net/url/FtpURLConnection.java
+++ b/luni/src/main/java/libcore/net/url/FtpURLConnection.java
@@ -35,7 +35,7 @@
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.security.Permission;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -350,7 +350,7 @@
             }
             code[i] = (byte) tmp;
         }
-        replyCode = new String(code, 0, code.length, Charsets.ISO_8859_1);
+        replyCode = new String(code, 0, code.length, StandardCharsets.ISO_8859_1);
 
         boolean multiline = false;
         if (ctrlInput.read() == '-') {
@@ -497,6 +497,6 @@
     }
 
     private void write(String command) throws IOException {
-        ctrlOutput.write(command.getBytes(Charsets.ISO_8859_1));
+        ctrlOutput.write(command.getBytes(StandardCharsets.ISO_8859_1));
     }
 }
diff --git a/luni/src/main/java/libcore/net/url/JarURLConnectionImpl.java b/luni/src/main/java/libcore/net/url/JarURLConnectionImpl.java
index 9a2c898..762f0e2 100644
--- a/luni/src/main/java/libcore/net/url/JarURLConnectionImpl.java
+++ b/luni/src/main/java/libcore/net/url/JarURLConnectionImpl.java
@@ -47,7 +47,7 @@
  */
 public class JarURLConnectionImpl extends JarURLConnection {
 
-    static HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>();
+    private static final HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>();
 
     private URL jarFileURL;
 
@@ -67,8 +67,7 @@
      * @throws IOException
      *             if there is a problem opening the connection.
      */
-    public JarURLConnectionImpl(URL url) throws MalformedURLException,
-            IOException {
+    public JarURLConnectionImpl(URL url) throws MalformedURLException, IOException {
         super(url);
         jarFileURL = getJarFileURL();
         jarFileURLConnection = jarFileURL.openConnection();
@@ -89,8 +88,6 @@
     /**
      * Returns the Jar file referred by this {@code URLConnection}.
      *
-     * @return the JAR file referenced by this connection
-     *
      * @throws IOException
      *             thrown if an IO error occurs while connecting to the
      *             resource.
@@ -108,13 +105,12 @@
      *             if an IO error occurs while connecting to the resource.
      */
     private void findJarFile() throws IOException {
-        JarFile jar = null;
         if (getUseCaches()) {
             synchronized (jarCache) {
                 jarFile = jarCache.get(jarFileURL);
             }
             if (jarFile == null) {
-                jar = openJarFile();
+                JarFile jar = openJarFile();
                 synchronized (jarCache) {
                     jarFile = jarCache.get(jarFileURL);
                     if (jarFile == null) {
@@ -134,7 +130,7 @@
         }
     }
 
-    JarFile openJarFile() throws IOException {
+    private JarFile openJarFile() throws IOException {
         if (jarFileURL.getProtocol().equals("file")) {
             String decodedFile = UriCodec.decode(jarFileURL.getFile());
             return new JarFile(new File(decodedFile), true, ZipFile.OPEN_READ);
@@ -346,26 +342,6 @@
         jarFileURLConnection.setDefaultUseCaches(defaultusecaches);
     }
 
-    /**
-     * Closes the cached files.
-     */
-    public static void closeCachedFiles() {
-        Set<Map.Entry<URL, JarFile>> s = jarCache.entrySet();
-        synchronized (jarCache) {
-            Iterator<Map.Entry<URL, JarFile>> i = s.iterator();
-            while (i.hasNext()) {
-                try {
-                    ZipFile zip = i.next().getValue();
-                    if (zip != null) {
-                        zip.close();
-                    }
-                } catch (IOException e) {
-                    // Ignored
-                }
-            }
-        }
-    }
-
     private class JarURLConnectionInputStream extends FilterInputStream {
         final JarFile jarFile;
 
diff --git a/luni/src/main/java/libcore/reflect/AnnotationAccess.java b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
new file mode 100644
index 0000000..fe740de
--- /dev/null
+++ b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.reflect;
+
+import com.android.dex.ClassDef;
+import com.android.dex.Dex;
+import com.android.dex.EncodedValueReader;
+import com.android.dex.FieldId;
+import com.android.dex.MethodId;
+import com.android.dex.ProtoId;
+import com.android.dex.TypeList;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Inherited;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import libcore.util.EmptyArray;
+
+/**
+ * Look up annotations from a dex file.
+ */
+public final class AnnotationAccess {
+    private AnnotationAccess() {
+    }
+
+    /*
+     * Classes like arrays, primitives and proxies will not have a Dex file.
+     * Such classes never have annotations.
+     */
+
+    private static final Class<?>[] NO_ARGUMENTS = null;
+    @SuppressWarnings("unused")
+    private static final byte VISIBILITY_BUILD = 0x00;
+    private static final byte VISIBILITY_RUNTIME = 0x01;
+    @SuppressWarnings("unused")
+    private static final byte VISIBILITY_SYSTEM = 0x02;
+
+    /*
+     * Class annotations. This includes declared class annotations plus
+     * annotations on the superclass that have @Inherited.
+     */
+
+    public static <A extends java.lang.annotation.Annotation> A getAnnotation(
+            Class<?> c, Class<A> annotationType) {
+        if (annotationType == null) {
+            throw new NullPointerException("annotationType == null");
+        }
+
+        A annotation = getDeclaredAnnotation(c, annotationType);
+        if (annotation != null) {
+            return annotation;
+        }
+
+        if (isInherited(annotationType)) {
+            for (Class<?> sup = c.getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+                annotation = getDeclaredAnnotation(sup, annotationType);
+                if (annotation != null) {
+                    return annotation;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns true if {@code annotationType} annotations on the superclass
+     * apply to subclasses that don't have another annotation of the same
+     * type.
+     */
+    private static boolean isInherited(Class<? extends Annotation> annotationType) {
+        return isDeclaredAnnotationPresent(annotationType, Inherited.class);
+    }
+
+    public static Annotation[] getAnnotations(Class<?> c) {
+        /*
+         * We need to get the annotations declared on this class, plus the
+         * annotations from superclasses that have the "@Inherited" annotation
+         * set.  We create a temporary map to use while we accumulate the
+         * annotations and convert it to an array at the end.
+         *
+         * It's possible to have duplicates when annotations are inherited.
+         * We use a Map to filter those out.
+         *
+         * HashMap might be overkill here.
+         */
+        HashMap<Class<?>, Annotation> map = new HashMap<Class<?>, Annotation>();
+        for (Annotation declaredAnnotation : getDeclaredAnnotations(c)) {
+            map.put(declaredAnnotation.annotationType(), declaredAnnotation);
+        }
+        for (Class<?> sup = c.getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+            for (Annotation declaredAnnotation : getDeclaredAnnotations(sup)) {
+                Class<? extends Annotation> clazz = declaredAnnotation.annotationType();
+                if (!map.containsKey(clazz) && isInherited(clazz)) {
+                    map.put(clazz, declaredAnnotation);
+                }
+            }
+        }
+
+        /* convert annotation values from HashMap to array */
+        Collection<Annotation> coll = map.values();
+        return coll.toArray(new Annotation[coll.size()]);
+    }
+
+    /**
+     * Returns true if {@code c} is annotated by {@code annotationType}.
+     */
+    public static boolean isAnnotationPresent(
+            Class<?> c, Class<? extends Annotation> annotationType) {
+        if (annotationType == null) {
+            throw new NullPointerException("annotationType == null");
+        }
+
+        if (isDeclaredAnnotationPresent(c, annotationType)) {
+            return true;
+        }
+
+        if (isInherited(annotationType)) {
+            for (Class<?> sup = c.getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+                if (isDeclaredAnnotationPresent(sup, annotationType)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /*
+     * Class, Field, Method, Constructor and Parameter annotations
+     */
+
+    /**
+     * Returns the annotations on {@code element}.
+     */
+    public static List<Annotation> getDeclaredAnnotations(AnnotatedElement element) {
+        int offset = getAnnotationSetOffset(element);
+        return annotationSetToAnnotations(getDexClass(element), offset);
+    }
+
+    /**
+     * Returns the annotation if it exists.
+     */
+    public static <A extends Annotation> A getDeclaredAnnotation(
+            AnnotatedElement element, Class<A> annotationClass) {
+        com.android.dex.Annotation a = getMethodAnnotation(element, annotationClass);
+        return a != null
+                ? toAnnotationInstance(getDexClass(element), annotationClass, a)
+                : null;
+    }
+
+    /**
+     * Returns true if the annotation exists.
+     */
+    public static boolean isDeclaredAnnotationPresent(
+            AnnotatedElement element, Class<? extends Annotation> annotationClass) {
+        return getMethodAnnotation(element, annotationClass) != null;
+    }
+
+    private static com.android.dex.Annotation getMethodAnnotation(
+            AnnotatedElement element, Class<? extends Annotation> annotationClass) {
+        Class<?> dexClass = getDexClass(element);
+        Dex dex = dexClass.getDex();
+        int annotationTypeIndex = getTypeIndex(dex, annotationClass);
+        if (annotationTypeIndex == -1) {
+            return null; // the dex file doesn't use this annotation
+        }
+
+        int annotationSetOffset = getAnnotationSetOffset(element);
+        return getAnnotationFromAnnotationSet(dex, annotationSetOffset, annotationTypeIndex);
+    }
+
+    /**
+     * @param element a class, a field, a method or a constructor.
+     */
+    private static int getAnnotationSetOffset(AnnotatedElement element) {
+        Class<?> dexClass = getDexClass(element);
+        int directoryOffset = getDirectoryOffset(dexClass);
+        if (directoryOffset == 0) {
+            return 0; // nothing on this class has annotations
+        }
+
+        Dex.Section directoryIn = dexClass.getDex().open(directoryOffset);
+        int classSetOffset = directoryIn.readInt();
+        if (element instanceof Class) {
+            return classSetOffset;
+        }
+
+        int fieldsSize = directoryIn.readInt();
+        int methodsSize = directoryIn.readInt();
+        directoryIn.readInt(); // parameters size
+
+        int fieldIndex = element instanceof Field ? ((Field) element).getDexFieldIndex() : -1;
+        for (int i = 0; i < fieldsSize; i++) {
+            int candidateFieldIndex = directoryIn.readInt();
+            int annotationSetOffset = directoryIn.readInt();
+            if (candidateFieldIndex == fieldIndex) {
+                return annotationSetOffset;
+            }
+        }
+        // we must read all fields prior to methods, if we were searching for a field then we missed
+        if (element instanceof Field) {
+            return 0;
+        }
+
+        int methodIndex= element instanceof Method ? ((Method) element).getDexMethodIndex()
+                                                   : ((Constructor<?>) element).getDexMethodIndex();
+        for (int i = 0; i < methodsSize; i++) {
+            int candidateMethodIndex = directoryIn.readInt();
+            int annotationSetOffset = directoryIn.readInt();
+            if (candidateMethodIndex == methodIndex) {
+                return annotationSetOffset;
+            }
+        }
+
+        return 0;
+    }
+
+    /**
+     * Returns {@code element} if it is a class; and the class declaring
+     * {@code element} otherwise. The dex file of the returned class also
+     * defines {@code element}.
+     */
+    private static Class<?> getDexClass(AnnotatedElement element) {
+        return element instanceof Class
+                ? ((Class<?>) element)
+                : ((Member) element).getDeclaringClass();
+    }
+
+    public static int getFieldIndex(Class<?> declaringClass, Class<?> type, String name) {
+        Dex dex = declaringClass.getDex();
+        int declaringClassIndex = getTypeIndex(dex, declaringClass);
+        int typeIndex = getTypeIndex(dex, type);
+        int nameIndex = getStringIndex(dex, name);
+        FieldId fieldId = new FieldId(dex, declaringClassIndex, typeIndex, nameIndex);
+        return Collections.binarySearch(dex.fieldIds(), fieldId);
+    }
+
+    public static int getMethodIndex(Class<?> declaringClass, String name, int protoIndex) {
+        Dex dex = declaringClass.getDex();
+        int declaringClassIndex = getTypeIndex(dex, declaringClass);
+        int nameIndex = getStringIndex(dex, name);
+        MethodId methodId = new MethodId(dex, declaringClassIndex, protoIndex, nameIndex);
+        return Collections.binarySearch(dex.methodIds(), methodId);
+    }
+
+    /**
+     * Returns the parameter annotations on {@code member}.
+     */
+    public static Annotation[][] getParameterAnnotations(Member member) {
+        Class<?> declaringClass = member.getDeclaringClass();
+        Dex dex = declaringClass.getDex();
+        int methodDexIndex;
+        if (member instanceof Method) {
+            methodDexIndex = ((Method) member).getDexMethodIndex();
+        } else {
+            methodDexIndex = ((Constructor<?>) member).getDexMethodIndex();
+        }
+        int protoIndex = dex.methodIds().get(methodDexIndex).getProtoIndex();
+        ProtoId proto = dex.protoIds().get(protoIndex);
+        TypeList parametersList = dex.readTypeList(proto.getParametersOffset());
+        short[] types = parametersList.getTypes();
+        int typesCount = types.length;
+
+        int directoryOffset = getDirectoryOffset(declaringClass);
+        if (directoryOffset == 0) {
+            return new Annotation[typesCount][0]; // nothing on this class has annotations
+        }
+
+        Dex.Section directoryIn = dex.open(directoryOffset);
+        directoryIn.readInt(); // class annotations
+        int fieldsSize = directoryIn.readInt();
+        int methodsSize = directoryIn.readInt();
+        int parametersSize = directoryIn.readInt();
+
+        for (int i = 0; i < fieldsSize; i++) {
+            directoryIn.readInt(); // field_index
+            directoryIn.readInt(); // annotation_set
+        }
+
+        for (int i = 0; i < methodsSize; i++) {
+            directoryIn.readInt(); // method_index
+            directoryIn.readInt(); // annotation_set
+        }
+
+        for (int i = 0; i < parametersSize; i++) {
+            int candidateMethodDexIndex = directoryIn.readInt();
+            int annotationSetRefListOffset = directoryIn.readInt();
+            if (candidateMethodDexIndex != methodDexIndex) {
+                continue;
+            }
+
+            Dex.Section refList = dex.open(annotationSetRefListOffset);
+            int parameterCount = refList.readInt();
+            Annotation[][] result = new Annotation[parameterCount][];
+            for (int p = 0; p < parameterCount; p++) {
+                int annotationSetOffset = refList.readInt();
+                List<Annotation> annotations
+                        = annotationSetToAnnotations(declaringClass, annotationSetOffset);
+                result[p] = annotations.toArray(new Annotation[annotations.size()]);
+            }
+            return result;
+        }
+
+        return new Annotation[typesCount][0];
+    }
+
+    /*
+     * System annotations.
+     */
+
+    public static Object getDefaultValue(Method method) {
+        /*
+         * Dex represents this with @AnnotationDefault on annotations that have
+         * default values:
+         *
+         * @AnnotationDefault(value=@Foo(a=7))
+         * public @interface Foo {
+         *   int a() default 7;
+         *   int b();
+         * }
+         */
+
+        Class<?> annotationClass = method.getDeclaringClass();
+        Dex dex = annotationClass.getDex();
+        EncodedValueReader reader = getOnlyAnnotationValue(
+                dex, annotationClass, "Ldalvik/annotation/AnnotationDefault;");
+        if (reader == null) {
+            return null;
+        }
+
+        int fieldCount = reader.readAnnotation();
+        if (reader.getAnnotationType() != getTypeIndex(dex, annotationClass)) {
+            throw new AssertionError("annotation value type != annotation class");
+        }
+
+        int methodNameIndex = Collections.binarySearch(dex.strings(), method.getName());
+        for (int i = 0; i < fieldCount; i++) {
+            int candidateNameIndex = reader.readAnnotationName();
+            if (candidateNameIndex == methodNameIndex) {
+                Class<?> returnType = method.getReturnType();
+                return decodeValue(annotationClass, returnType, dex, reader);
+            } else {
+                reader.skipValue();
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the class of which {@code c} is a direct member. If {@code c} is
+     * defined in a method or constructor, this is not transitive.
+     */
+    public static Class<?> getDeclaringClass(Class<?> c) {
+        /*
+         * public class Bar {
+         *   @EnclosingClass(value=Bar)
+         *   public class Foo {}
+         * }
+         */
+        Dex dex = c.getDex();
+        EncodedValueReader reader = getOnlyAnnotationValue(
+                dex, c, "Ldalvik/annotation/EnclosingClass;");
+        if (reader == null) {
+            return null;
+        }
+        return indexToType(c, dex, reader.readType());
+    }
+
+    public static AccessibleObject getEnclosingMethodOrConstructor(Class<?> c) {
+        /*
+         * public class Bar {
+         *   public void quux(String s, int i) {
+         *     @EnclosingMethod(value=Bar.quux(String,int))
+         *     class Foo {}
+         *   }
+         * }
+         */
+        Dex dex = c.getDex();
+        EncodedValueReader reader = getOnlyAnnotationValue(
+                dex, c, "Ldalvik/annotation/EnclosingMethod;");
+        if (reader == null) {
+            return null;
+        }
+        return indexToMethod(c, dex, reader.readMethod());
+    }
+
+    public static Class<?>[] getMemberClasses(Class<?> c) {
+        /*
+         * @MemberClasses(value=[Bar, Baz])
+         * public class Foo {
+         *   class Bar {}
+         *   class Baz {}
+         * }
+         */
+        Dex dex = c.getDex();
+        EncodedValueReader reader = getOnlyAnnotationValue(
+                dex, c, "Ldalvik/annotation/MemberClasses;");
+        if (reader == null) {
+            return EmptyArray.CLASS;
+        }
+        return (Class[]) decodeValue(c, Class[].class, dex, reader);
+    }
+
+    /**
+     * @param element a class, a field, a method or a constructor.
+     */
+    public static String getSignature(AnnotatedElement element) {
+        /*
+         * @Signature(value=["Ljava/util/List", "<", "Ljava/lang/String;", ">;"])
+         * List<String> foo;
+         */
+        Class<?> dexClass = getDexClass(element);
+        Dex dex = dexClass.getDex();
+        EncodedValueReader reader = getOnlyAnnotationValue(
+                dex, element, "Ldalvik/annotation/Signature;");
+        if (reader == null) {
+            return null;
+        }
+        String[] array = (String[]) decodeValue(dexClass, String[].class, dex, reader);
+        StringBuilder result = new StringBuilder();
+        for (String s : array) {
+            result.append(s);
+        }
+        return result.toString();
+    }
+
+    /**
+     * @param element a method or a constructor.
+     */
+    public static Class<?>[] getExceptions(AnnotatedElement element) {
+        /*
+         * @Throws(value=[IOException.class])
+         * void foo() throws IOException;
+         */
+        Class<?> dexClass = getDexClass(element);
+        Dex dex = dexClass.getDex();
+        EncodedValueReader reader = getOnlyAnnotationValue(
+                dex, element, "Ldalvik/annotation/Throws;");
+        if (reader == null) {
+            return EmptyArray.CLASS;
+        }
+        return (Class<?>[]) decodeValue(dexClass, Class[].class, dex, reader);
+    }
+
+    public static int getInnerClassFlags(Class<?> c, int defaultValue) {
+        /*
+         * @InnerClass(accessFlags=0x01,name="Foo")
+         * class Foo {};
+         */
+        Dex dex = c.getDex();
+        EncodedValueReader reader = getAnnotationReader(
+                dex, c, "Ldalvik/annotation/InnerClass;", 2);
+        if (reader == null) {
+            return defaultValue;
+        }
+        reader.readAnnotationName(); // accessFlags
+        return reader.readInt();
+    }
+
+    public static String getInnerClassName(Class<?> c) {
+        /*
+         * @InnerClass(accessFlags=0x01,name="Foo")
+         * class Foo {};
+         */
+        Dex dex = c.getDex();
+        EncodedValueReader reader = getAnnotationReader(
+                dex, c, "Ldalvik/annotation/InnerClass;", 2);
+        if (reader == null) {
+            return null;
+        }
+        reader.readAnnotationName(); // accessFlags
+        reader.readInt();
+        reader.readAnnotationName(); // name
+        return reader.peek() == EncodedValueReader.ENCODED_NULL
+                ? null
+                : (String) decodeValue(c, String.class, dex, reader);
+    }
+
+    public static boolean isAnonymousClass(Class<?> c) {
+        /*
+         * @InnerClass(accessFlags=0x01,name="Foo")
+         * class Foo {};
+         */
+        Dex dex = c.getDex();
+        EncodedValueReader reader = getAnnotationReader(
+                dex, c, "Ldalvik/annotation/InnerClass;", 2);
+        if (reader == null) {
+            return false;
+        }
+        reader.readAnnotationName(); // accessFlags
+        reader.readInt();
+        reader.readAnnotationName(); // name
+        return reader.peek() == EncodedValueReader.ENCODED_NULL;
+    }
+
+    /*
+     * Dex support.
+     *
+     * Different classes come from different Dex files. This class is careful
+     * to guarantee that Dex-relative indices and encoded values are interpreted
+     * using the Dex that they were read from. Methods that use Dex-relative
+     * values accept that Dex as a parameter or the class from which that Dex
+     * was derived.
+     */
+
+    private static int getTypeIndex(Dex dex, Class<?> c) {
+        return dex == c.getDex() ? c.getTypeIndex() : computeTypeIndex(dex, c);
+    }
+
+    public static int computeTypeIndex(Dex dex, Class<?> c) {
+        if (dex == null) {
+            return -1;
+        }
+        int typeIndex = Collections.binarySearch(dex.typeNames(), InternalNames.getInternalName(c));
+        if (typeIndex < 0) {
+            typeIndex = -1;
+        }
+        return typeIndex;
+    }
+
+    private static int getStringIndex(Dex dex, String string) {
+        return Collections.binarySearch(dex.strings(), string);
+    }
+
+    private static int getDirectoryOffset(Class<?> c) {
+        return c.getAnnotationDirectoryOffset();
+    }
+
+    private static com.android.dex.Annotation getAnnotationFromAnnotationSet(
+            Dex dex, int annotationSetOffset, int annotationType) {
+        if (annotationSetOffset == 0) {
+            return null; // no annotation
+        }
+
+        Dex.Section setIn = dex.open(annotationSetOffset); // annotation_set_item
+        for (int i = 0, size = setIn.readInt(); i < size; i++) {
+            int annotationOffset = setIn.readInt();
+            Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item
+            com.android.dex.Annotation candidate = annotationIn.readAnnotation();
+            if (candidate.getTypeIndex() == annotationType) {
+                return candidate;
+            }
+        }
+
+        return null; // this set doesn't carry the annotation
+    }
+
+    private static EncodedValueReader getAnnotationReader(
+            Dex dex, AnnotatedElement element, String annotationName, int expectedFieldCount) {
+        int annotationSetOffset = getAnnotationSetOffset(element);
+        if (annotationSetOffset == 0) {
+            return null; // no annotations on the class
+        }
+
+        int annotationTypeIndex = Collections.binarySearch(dex.typeNames(), annotationName);
+        com.android.dex.Annotation annotation = getAnnotationFromAnnotationSet(
+                dex, annotationSetOffset, annotationTypeIndex);
+        if (annotation == null) {
+            return null; // no annotation
+        }
+
+        EncodedValueReader reader = annotation.getReader();
+        int fieldCount = reader.readAnnotation();
+        if (reader.getAnnotationType() != annotationTypeIndex) {
+            throw new AssertionError();
+        }
+        if (fieldCount != expectedFieldCount) {
+            return null; // not the expected values on this annotation; give up
+        }
+
+        return reader;
+    }
+
+    /**
+     * Returns a reader ready to read the only value of the annotation on
+     * {@code element}, or null if that annotation doesn't exist.
+     */
+    private static EncodedValueReader getOnlyAnnotationValue(
+            Dex dex, AnnotatedElement element, String annotationName) {
+        EncodedValueReader reader = getAnnotationReader(dex, element, annotationName, 1);
+        if (reader == null) {
+            return null;
+        }
+        reader.readAnnotationName(); // skip the name
+        return reader;
+    }
+
+    private static Class<? extends Annotation> getAnnotationClass(Class<?> context, Dex dex,
+                                                                  int typeIndex) {
+        try {
+            @SuppressWarnings("unchecked") // we do a runtime check
+            Class<? extends Annotation> result = (Class<? extends Annotation>) indexToType(context,
+                    dex, typeIndex);
+            if (!result.isAnnotation()) {
+                throw new IncompatibleClassChangeError("Expected annotation: " + result.getName());
+            }
+            return result;
+        } catch (NoClassDefFoundError ncdfe) {
+            return null;
+        }
+    }
+
+    private static Class<?> indexToType(Class<?> context, Dex dex, int typeIndex) {
+        String internalName = dex.typeNames().get(typeIndex);
+        return InternalNames.getClass(context.getClassLoader(), internalName);
+    }
+
+    private static AccessibleObject indexToMethod(Class<?> context, Dex dex, int methodIndex) {
+        MethodId methodId = dex.methodIds().get(methodIndex);
+        Class<?> declaringClass = indexToType(context, dex, methodId.getDeclaringClassIndex());
+        String name = dex.strings().get(methodId.getNameIndex());
+        Class<?>[] parametersArray = protoIndexToParameters(context, dex, methodId.getProtoIndex());
+        try {
+            return name.equals("<init>")
+                    ? declaringClass.getDeclaredConstructor(parametersArray)
+                    : declaringClass.getDeclaredMethod(name, parametersArray);
+        } catch (NoSuchMethodException e) {
+            throw new IncompatibleClassChangeError("Couldn't find " + declaringClass.getName()
+                    + "." + name + Arrays.toString(parametersArray));
+        }
+    }
+
+    public static Class<?>[] protoIndexToParameters(Class<?> context, Dex dex, int protoIndex) {
+        ProtoId proto = dex.protoIds().get(protoIndex);
+        TypeList parametersList = dex.readTypeList(proto.getParametersOffset());
+        short[] types = parametersList.getTypes();
+        Class<?>[] parametersArray = new Class[types.length];
+        for (int i = 0; i < types.length; i++) {
+            parametersArray[i] = indexToType(context, dex, types[i]);
+        }
+        return parametersArray;
+    }
+
+    public static Class<?>[] typeIndexToInterfaces(Class<?> context, Dex dex, int typeIndex) {
+        ClassDef def = getClassDef(dex, typeIndex);
+        if (def == null) {
+          return EmptyArray.CLASS;
+        }
+        short[] interfaces = def.getInterfaces();
+        Class<?>[] result = new Class<?>[interfaces.length];
+        for (int i = 0; i < interfaces.length; i++) {
+            result[i] = indexToType(context, dex, interfaces[i]);
+        }
+        return result;
+    }
+
+    public static int typeIndexToAnnotationDirectoryOffset(Dex dex, int typeIndex) {
+        ClassDef def = getClassDef(dex, typeIndex);
+        return def == null ? 0 : def.getAnnotationsOffset();
+    }
+
+    private static ClassDef getClassDef(Dex dex, int typeIndex) {
+        if (typeIndex == -1) {
+            return null;
+        }
+        for (ClassDef def : dex.classDefs()) {
+            if (def.getTypeIndex() == typeIndex) {
+                return def;
+            }
+        }
+        throw new AssertionError();
+    }
+
+    private static List<Annotation> annotationSetToAnnotations(Class<?> context, int offset) {
+        if (offset == 0) {
+            return Collections.emptyList(); // no annotations in the set
+        }
+
+        Dex dex = context.getDex();
+        Dex.Section setIn = dex.open(offset); // annotation_set_item
+        int size = setIn.readInt();
+        List<Annotation> result = new ArrayList<Annotation>(size);
+
+        for (int i = 0; i < size; i++) {
+            int annotationOffset = setIn.readInt();
+            Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item
+            com.android.dex.Annotation annotation = annotationIn.readAnnotation();
+            if (annotation.getVisibility() != VISIBILITY_RUNTIME) {
+                continue;
+            }
+            Class<? extends Annotation> annotationClass =
+                    getAnnotationClass(context, dex, annotation.getTypeIndex());
+            if (annotationClass != null) {
+                result.add(toAnnotationInstance(context, dex, annotationClass, annotation.getReader()));
+            }
+        }
+        return result;
+    }
+
+    private static <A extends Annotation> A toAnnotationInstance(Class<?> context,
+            Class<A> annotationClass, com.android.dex.Annotation annotation) {
+        return toAnnotationInstance(context, context.getDex(), annotationClass,
+                annotation.getReader());
+    }
+
+    private static <A extends Annotation> A toAnnotationInstance(Class<?> context, Dex dex,
+            Class<A> annotationClass, EncodedValueReader reader) {
+        int fieldCount = reader.readAnnotation();
+        if (annotationClass != indexToType(context, dex, reader.getAnnotationType())) {
+            throw new AssertionError("annotation value type != return type");
+        }
+        AnnotationMember[] members = new AnnotationMember[fieldCount];
+        for (int i = 0; i < fieldCount; i++) {
+            int name = reader.readAnnotationName();
+            String nameString = dex.strings().get(name);
+            Method method;
+            try {
+                method = annotationClass.getMethod(nameString, NO_ARGUMENTS);
+            } catch (NoSuchMethodException e) {
+                throw new IncompatibleClassChangeError(
+                        "Couldn't find " + annotationClass.getName() + "." + nameString);
+            }
+            Class<?> returnType = method.getReturnType();
+            Object value = decodeValue(context, returnType, dex, reader);
+            members[i] = new AnnotationMember(nameString, value, returnType, method);
+        }
+        return AnnotationFactory.createAnnotation(annotationClass, members);
+    }
+
+    private static Object decodeValue(Class<?> context, Class<?> type,
+            Dex dex, EncodedValueReader reader) {
+        if (type.isArray()) {
+            int size = reader.readArray();
+            Class<?> componentType = type.getComponentType();
+            Object array = Array.newInstance(componentType, size);
+            for (int i = 0; i < size; i++) {
+                Array.set(array, i, decodeValue(context, componentType, dex, reader));
+            }
+            return array;
+        } else if (type.isEnum()) {
+            int fieldIndex = reader.readEnum();
+            FieldId fieldId = dex.fieldIds().get(fieldIndex);
+            String enumName = dex.strings().get(fieldId.getNameIndex());
+            @SuppressWarnings({"unchecked", "rawtypes"}) // Class.isEnum is the runtime check
+            Class<? extends Enum> enumType = (Class<? extends Enum>) type;
+            return Enum.valueOf(enumType, enumName);
+        } else if (type.isAnnotation()) {
+            @SuppressWarnings("unchecked") // Class.isAnnotation is the runtime check
+            Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) type;
+            return toAnnotationInstance(context, dex, annotationClass, reader);
+        } else if (type == String.class) {
+            int index = reader.readString();
+            return dex.strings().get(index);
+        } else if (type == Class.class) {
+            int index = reader.readType();
+            return indexToType(context, dex, index);
+        } else if (type == byte.class) {
+            return reader.readByte();
+        } else if (type == short.class) {
+            return reader.readShort();
+        } else if (type == int.class) {
+            return reader.readInt();
+        } else if (type == long.class) {
+            return reader.readLong();
+        } else if (type == float.class) {
+            return reader.readFloat();
+        } else if (type == double.class) {
+            return reader.readDouble();
+        } else if (type == char.class) {
+            return reader.readChar();
+        } else if (type == boolean.class) {
+            return reader.readBoolean();
+        } else {
+            // is null legit?
+            throw new AssertionError("Unexpected annotation value type: " + type);
+        }
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationFactory.java b/luni/src/main/java/libcore/reflect/AnnotationFactory.java
similarity index 79%
rename from luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationFactory.java
rename to luni/src/main/java/libcore/reflect/AnnotationFactory.java
index 3fd13f5..272754a 100644
--- a/luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationFactory.java
+++ b/luni/src/main/java/libcore/reflect/AnnotationFactory.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.lang.annotation;
+package libcore.reflect;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
@@ -29,8 +29,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.WeakHashMap;
-import static org.apache.harmony.lang.annotation.AnnotationMember.ARRAY;
-import static org.apache.harmony.lang.annotation.AnnotationMember.ERROR;
 
 /**
  * The annotation implementation based on dynamically generated proxy instances.
@@ -41,7 +39,7 @@
  * conforming access to annotation member values and required implementations of
  * methods declared in Annotation interface.
  *
- * @see android.lang.annotation.AnnotationMember
+ * @see AnnotationMember
  * @see java.lang.annotation.Annotation
  *
  * @author Alexey V. Varlamov, Serguei S. Zapreyev
@@ -50,35 +48,36 @@
 @SuppressWarnings({"serial"})
 public final class AnnotationFactory implements InvocationHandler, Serializable {
 
-    private static final transient
-    Map<Class<? extends Annotation>, AnnotationMember[]>
-    cache = new WeakHashMap<Class<? extends Annotation>, AnnotationMember[]>();
+    private static final transient Map<Class<? extends Annotation>, AnnotationMember[]> cache =
+            new WeakHashMap<Class<? extends Annotation>, AnnotationMember[]>();
 
     /**
      * Reflects specified annotation type and returns an array
      * of member element definitions with default values.
      */
-    public static AnnotationMember[] getElementsDescription(Class<? extends Annotation> annotationType ) {
-        AnnotationMember[] desc = cache.get(annotationType);
-        if (desc == null) {
-            if (!annotationType.isAnnotation()) {
-                throw new IllegalArgumentException("Type is not annotation: "
-                        + annotationType.getName());
+    public static AnnotationMember[] getElementsDescription(Class<? extends Annotation> annotationType) {
+        synchronized (cache) {
+            AnnotationMember[] desc = cache.get(annotationType);
+            if (desc != null) {
+                return desc;
             }
-            Method[] m = annotationType.getDeclaredMethods();
-            desc = new AnnotationMember[m.length];
-            int idx = 0;
-            for (Method element : m) {
-                String name = element.getName();
-                Class<?> type = element.getReturnType();
-                try {
-                    desc[idx] = new AnnotationMember(name,
-                            element.getDefaultValue(), type, element);
-                } catch (Throwable t) {
-                    desc[idx] = new AnnotationMember(name, t, type, element);
-                }
-                idx++;
+        }
+        if (!annotationType.isAnnotation()) {
+            throw new IllegalArgumentException("Type is not annotation: " + annotationType.getName());
+        }
+        Method[] declaredMethods = annotationType.getDeclaredMethods();
+        AnnotationMember[] desc = new AnnotationMember[declaredMethods.length];
+        for (int i = 0; i < declaredMethods.length; ++i) {
+            Method element = declaredMethods[i];
+            String name = element.getName();
+            Class<?> type = element.getReturnType();
+            try {
+                desc[i] = new AnnotationMember(name, element.getDefaultValue(), type, element);
+            } catch (Throwable t) {
+                desc[i] = new AnnotationMember(name, t, type, element);
             }
+        }
+        synchronized (cache) {
             cache.put(annotationType, desc);
         }
         return desc;
@@ -90,13 +89,11 @@
      * @param elements name-value pairs representing elements of the annotation
      * @return a new annotation instance
      */
-    public static Annotation createAnnotation(
-            Class<? extends Annotation> annotationType,
-            AnnotationMember[] elements)
-    {
-        AnnotationFactory antn = new AnnotationFactory(annotationType, elements);
-        return (Annotation)Proxy.newProxyInstance( annotationType.getClassLoader(),
-                new Class[]{annotationType}, antn);
+    public static <A extends Annotation> A createAnnotation(Class<? extends Annotation> annotationType,
+                                                            AnnotationMember[] elements) {
+        AnnotationFactory factory = new AnnotationFactory(annotationType, elements);
+        return (A) Proxy.newProxyInstance(annotationType.getClassLoader(),
+                                          new Class[]{annotationType}, factory);
     }
 
     private final Class<? extends Annotation> klazz;
@@ -118,8 +115,8 @@
         } else {
             //merge default and actual values
             elements = new AnnotationMember[defs.length];
-            next: for (int i = elements.length - 1; i >= 0; i-- ){
-                for (AnnotationMember val : values){
+            next: for (int i = elements.length - 1; i >= 0; i--) {
+                for (AnnotationMember val : values) {
                     if (val.name.equals(defs[i].name)) {
                         elements[i] = val.setDefinition(defs[i]);
                         continue next;
@@ -134,8 +131,7 @@
      * Reads the object, obtains actual member definitions for the annotation type,
      * and merges deserialized values with the new definitions.
      */
-    private void readObject(ObjectInputStream os) throws IOException,
-    ClassNotFoundException {
+    private void readObject(ObjectInputStream os) throws IOException, ClassNotFoundException {
         os.defaultReadObject();
         // Annotation type members can be changed arbitrarily
         // So there may be zombi elements from the previous life;
@@ -145,8 +141,7 @@
         // but seems better to keep them for compatibility
         AnnotationMember[] defs = getElementsDescription(klazz);
         AnnotationMember[] old = elements;
-        List<AnnotationMember> merged = new ArrayList<AnnotationMember>(
-                defs.length + old.length);
+        List<AnnotationMember> merged = new ArrayList<AnnotationMember>(defs.length + old.length);
         nextOld: for (AnnotationMember el1 : old) {
             for (AnnotationMember el2 : defs) {
                 if (el2.name.equals(el1.name)) {
@@ -155,8 +150,8 @@
             }
             merged.add(el1); //phantom element
         }
-        nextNew: for (AnnotationMember def : defs){
-            for (AnnotationMember val : old){
+        nextNew: for (AnnotationMember def : defs) {
+            for (AnnotationMember val : old) {
                 if (val.name.equals(def.name)) {
                     // nothing to do about cached errors (if any)
                     // anyway they remain relevant to values
@@ -177,7 +172,7 @@
      * differ completely from this class.
      * @return true if the passed object is equivalent annotation instance,
      * false otherwise.
-     * @see android.lang.annotation.AnnotationMember#equals(Object)
+     * @see AnnotationMember#equals(Object)
      */
     public boolean equals(Object obj) {
         if (obj == this) {
@@ -188,12 +183,12 @@
         }
         Object handler = null;
         if (Proxy.isProxyClass(obj.getClass())
-                && (handler = Proxy.getInvocationHandler(obj)) instanceof AnnotationFactory ) {
+                && (handler = Proxy.getInvocationHandler(obj)) instanceof AnnotationFactory) {
             AnnotationFactory other = (AnnotationFactory) handler;
             if (elements.length != other.elements.length) {
                 return false;
             }
-            next: for (AnnotationMember el1 : elements){
+            next: for (AnnotationMember el1 : elements) {
                 for (AnnotationMember el2 : other.elements) {
                     if (el1.equals(el2)) {
                         continue next;
@@ -203,11 +198,11 @@
             }
             return true;
         } else {
-            // encountered foreign annotation implementaton
+            // encountered foreign annotation implementation
             // so have to obtain element values via invocation
             // of corresponding methods
             for (final AnnotationMember el : elements) {
-                if (el.tag == ERROR) {
+                if (el.tag == AnnotationMember.ERROR) {
                     // undefined value is incomparable (transcendent)
                     return false;
                 }
@@ -216,8 +211,8 @@
                         el.definingMethod.setAccessible(true);
                     }
                     Object otherValue = el.definingMethod.invoke(obj);
-                    if (otherValue != null ) {
-                        if (el.tag == ARRAY) {
+                    if (otherValue != null) {
+                        if (el.tag == AnnotationMember.ARRAY) {
                             if (!el.equalArrayValue(otherValue)) {
                                 return false;
                             }
@@ -240,7 +235,7 @@
     /**
      * Returns a hash code composed as a sum of hash codes of member elements,
      * including elements with default values.
-     * @see android.lang.annotation.AnnotationMember#hashCode()
+     * @see AnnotationMember#hashCode()
      */
     public int hashCode() {
         int hash = 0;
@@ -278,8 +273,7 @@
      * @throws IllegalArgumentException If the specified method is none of the above
      * @return the invocation result
      */
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
-    {
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         String name = method.getName();
         Class[] params = method.getParameterTypes();
         if (params.length == 0) {
@@ -308,10 +302,9 @@
                 }
                 return value;
             }
-        } else if (params.length == 1 && params[0] == Object.class && "equals".equals(name)){
+        } else if (params.length == 1 && params[0] == Object.class && "equals".equals(name)) {
             return Boolean.valueOf(equals(args[0]));
         }
-        throw new IllegalArgumentException(
-                "Invalid method for annotation type: " + method);
+        throw new IllegalArgumentException("Invalid method for annotation type: " + method);
     }
 }
diff --git a/luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationMember.java b/luni/src/main/java/libcore/reflect/AnnotationMember.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationMember.java
rename to luni/src/main/java/libcore/reflect/AnnotationMember.java
index f64332a..7ca4abf 100644
--- a/luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationMember.java
+++ b/luni/src/main/java/libcore/reflect/AnnotationMember.java
@@ -15,7 +15,7 @@
  *  limitations under the License.
  */
 
-package org.apache.harmony.lang.annotation;
+package libcore.reflect;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -45,13 +45,13 @@
  * class-data structures and throwing is delayed until the element
  * is requested for value.
  *
- * @see android.lang.annotation.AnnotationFactory
+ * @see AnnotationFactory
  *
  * @author Alexey V. Varlamov, Serguei S. Zapreyev
  * @version $Revision$
  */
 @SuppressWarnings({"serial"})
-public class AnnotationMember implements Serializable {
+public final class AnnotationMember implements Serializable {
 
     /**
      * Tag description of a Throwable value type.
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForArray.java b/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java
similarity index 81%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForArray.java
rename to luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java
index c9b76b1..ef22576 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForArray.java
+++ b/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
 
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.Type;
 
-public final class ImplForArray implements GenericArrayType {
+public final class GenericArrayTypeImpl implements GenericArrayType {
     private final Type componentType;
 
-    public ImplForArray(Type componentType) {
+    public GenericArrayTypeImpl(Type componentType) {
         this.componentType = componentType;
     }
 
     public Type getGenericComponentType() {
         try {
-            return ((ImplForType)componentType).getResolvedType();
+            return ((ParameterizedTypeImpl)componentType).getResolvedType();
         } catch (ClassCastException e) {
             return componentType;
         }
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/GenericSignatureParser.java b/luni/src/main/java/libcore/reflect/GenericSignatureParser.java
similarity index 87%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/GenericSignatureParser.java
rename to luni/src/main/java/libcore/reflect/GenericSignatureParser.java
index 490daaf..0c94eba 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/GenericSignatureParser.java
+++ b/luni/src/main/java/libcore/reflect/GenericSignatureParser.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.GenericDeclaration;
@@ -64,7 +64,9 @@
  * VoidDescriptor ::= "V".
  * </pre>
  */
-public class GenericSignatureParser {
+public final class GenericSignatureParser {
+
+    // TODO: unify this with InternalNames
 
     public ListOfTypes exceptionTypes;
     public ListOfTypes parameterTypes;
@@ -149,18 +151,11 @@
         if (!eof) {
             parseMethodTypeSignature(rawExceptionTypes);
         } else {
-            if(genericDecl instanceof Method) {
-                Method m = (Method) genericDecl;
-                this.formalTypeParameters = ListOfVariables.EMPTY;
-                this.parameterTypes = new ListOfTypes(m.getParameterTypes());
-                this.exceptionTypes = new ListOfTypes(m.getExceptionTypes());
-                this.returnType = m.getReturnType();
-            } else {
-                this.formalTypeParameters = ListOfVariables.EMPTY;
-                this.parameterTypes = ListOfTypes.EMPTY;
-                this.exceptionTypes = ListOfTypes.EMPTY;
-                this.returnType = void.class;
-            }
+            Method m = (Method) genericDecl;
+            this.formalTypeParameters = ListOfVariables.EMPTY;
+            this.parameterTypes = new ListOfTypes(m.getParameterTypes());
+            this.exceptionTypes = new ListOfTypes(m.getExceptionTypes());
+            this.returnType = m.getReturnType();
         }
     }
 
@@ -177,16 +172,10 @@
         if (!eof) {
             parseMethodTypeSignature(rawExceptionTypes);
         } else {
-            if(genericDecl instanceof Constructor) {
-                Constructor c = (Constructor) genericDecl;
-                this.formalTypeParameters = ListOfVariables.EMPTY;
-                this.parameterTypes = new ListOfTypes(c.getParameterTypes());
-                this.exceptionTypes = new ListOfTypes(c.getExceptionTypes());
-            } else {
-                this.formalTypeParameters = ListOfVariables.EMPTY;
-                this.parameterTypes = ListOfTypes.EMPTY;
-                this.exceptionTypes = ListOfTypes.EMPTY;
-            }
+            Constructor c = (Constructor) genericDecl;
+            this.formalTypeParameters = ListOfVariables.EMPTY;
+            this.parameterTypes = new ListOfTypes(c.getParameterTypes());
+            this.exceptionTypes = new ListOfTypes(c.getExceptionTypes());
         }
     }
 
@@ -243,7 +232,7 @@
         this.formalTypeParameters = typeParams.getArray();
     }
 
-    ImplForVariable<GenericDeclaration> parseFormalTypeParameter() {
+    TypeVariableImpl<GenericDeclaration> parseFormalTypeParameter() {
         // FormalTypeParameter ::= Ident ClassBound {InterfaceBound}.
 
         scanIdentifier();
@@ -263,7 +252,7 @@
             bounds.add(parseFieldTypeSignature());
         }
 
-        return new ImplForVariable<GenericDeclaration>(genericDecl, name, bounds);
+        return new TypeVariableImpl<GenericDeclaration>(genericDecl, name, bounds);
     }
 
     Type parseFieldTypeSignature() {
@@ -276,7 +265,7 @@
         case '[':
             // ArrayTypeSignature ::= "[" TypSignature.
             scanSymbol();
-            return new ImplForArray(parseTypeSignature());
+            return new GenericArrayTypeImpl(parseTypeSignature());
         case 'T':
             return parseTypeVariableSignature();
         default:
@@ -301,9 +290,9 @@
         qualIdent.append(this.identifier);
 
         ListOfTypes typeArgs = parseOptTypeArguments();
-        ImplForType parentType =
-                new ImplForType(null, qualIdent.toString(), typeArgs, loader);
-        ImplForType type = parentType;
+        ParameterizedTypeImpl parentType =
+                new ParameterizedTypeImpl(null, qualIdent.toString(), typeArgs, loader);
+        ParameterizedTypeImpl type = parentType;
 
         while (symbol == '.') {
             // Deal with Member Classes:
@@ -311,7 +300,7 @@
             scanIdentifier();
             qualIdent.append("$").append(identifier); // FIXME: is "$" correct?
             typeArgs = parseOptTypeArguments();
-            type = new ImplForType(parentType, qualIdent.toString(), typeArgs,
+            type = new ParameterizedTypeImpl(parentType, qualIdent.toString(), typeArgs,
                     loader);
         }
 
@@ -343,32 +332,32 @@
         if (symbol == '*') {
             scanSymbol();
             extendsBound.add(Object.class);
-            return new ImplForWildcard(extendsBound, superBound);
+            return new WildcardTypeImpl(extendsBound, superBound);
         }
         else if (symbol == '+') {
             scanSymbol();
             extendsBound.add(parseFieldTypeSignature());
-            return new ImplForWildcard(extendsBound, superBound);
+            return new WildcardTypeImpl(extendsBound, superBound);
         }
         else if (symbol == '-') {
             scanSymbol();
             superBound.add(parseFieldTypeSignature());
             extendsBound.add(Object.class);
-            return new ImplForWildcard(extendsBound, superBound);
+            return new WildcardTypeImpl(extendsBound, superBound);
         }
         else {
             return parseFieldTypeSignature();
         }
     }
 
-    ImplForVariable<GenericDeclaration> parseTypeVariableSignature() {
+    TypeVariableImpl<GenericDeclaration> parseTypeVariableSignature() {
         // TypeVariableSignature ::= "T" Ident ";".
         expect('T');
         scanIdentifier();
         expect(';');
         // Reference to type variable:
         // Note: we don't know the declaring GenericDeclaration yet.
-        return new ImplForVariable<GenericDeclaration>(genericDecl, identifier);
+        return new TypeVariableImpl<GenericDeclaration>(genericDecl, identifier);
     }
 
     Type parseTypeSignature() {
@@ -504,5 +493,4 @@
             throw new GenericSignatureFormatError();
         }
     }
-
 }
diff --git a/luni/src/main/java/libcore/reflect/InternalNames.java b/luni/src/main/java/libcore/reflect/InternalNames.java
new file mode 100644
index 0000000..b9e65cb
--- /dev/null
+++ b/luni/src/main/java/libcore/reflect/InternalNames.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.reflect;
+
+import java.lang.reflect.Array;
+
+/**
+ * Work with a type's internal name like "V" or "Ljava/lang/String;".
+ */
+public final class InternalNames {
+    private InternalNames() {
+    }
+
+    public static Class<?> getClass(ClassLoader classLoader, String internalName) {
+        if (internalName.startsWith("[")) {
+            Class<?> componentClass = getClass(classLoader, internalName.substring(1));
+            return Array.newInstance(componentClass, 0).getClass();
+        } else if (internalName.equals("Z")) {
+            return boolean.class;
+        } else if (internalName.equals("B")) {
+            return byte.class;
+        } else if (internalName.equals("S")) {
+            return short.class;
+        } else if (internalName.equals("I")) {
+            return int.class;
+        } else if (internalName.equals("J")) {
+            return long.class;
+        } else if (internalName.equals("F")) {
+            return float.class;
+        } else if (internalName.equals("D")) {
+            return double.class;
+        } else if (internalName.equals("C")) {
+            return char.class;
+        } else if (internalName.equals("V")) {
+            return void.class;
+        } else {
+            String name = internalName.substring(1, internalName.length() - 1).replace('/', '.');
+            try {
+                return classLoader.loadClass(name);
+            } catch (ClassNotFoundException e) {
+                NoClassDefFoundError error = new NoClassDefFoundError(name);
+                error.initCause(e);
+                throw error;
+            }
+        }
+    }
+
+    public static String getInternalName(Class<?> c) {
+        if (c.isArray()) {
+            return '[' + getInternalName(c.getComponentType());
+        } else if (c == boolean.class) {
+            return "Z";
+        } else if (c == byte.class) {
+            return "B";
+        } else if (c == short.class) {
+            return "S";
+        } else if (c == int.class) {
+            return "I";
+        } else if (c == long.class) {
+            return "J";
+        } else if (c == float.class) {
+            return "F";
+        } else if (c == double.class) {
+            return "D";
+        } else if (c == char.class) {
+            return "C";
+        } else if (c == void.class) {
+            return "V";
+        } else {
+            return 'L' + c.getName().replace('.', '/') + ';';
+        }
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfTypes.java b/luni/src/main/java/libcore/reflect/ListOfTypes.java
similarity index 94%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfTypes.java
rename to luni/src/main/java/libcore/reflect/ListOfTypes.java
index 59470f52..c5d90e2 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfTypes.java
+++ b/luni/src/main/java/libcore/reflect/ListOfTypes.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
 
 import java.lang.reflect.Type;
 import java.util.ArrayList;
@@ -58,7 +58,7 @@
         for (int i = 0; i < unresolved.size(); i++) {
             Type type = unresolved.get(i);
             try {
-                result[i] = ((ImplForType) type).getResolvedType();
+                result[i] = ((ParameterizedTypeImpl) type).getResolvedType();
             } catch (ClassCastException e) {
                 result[i] = type;
             }
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfVariables.java b/luni/src/main/java/libcore/reflect/ListOfVariables.java
similarity index 80%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfVariables.java
rename to luni/src/main/java/libcore/reflect/ListOfVariables.java
index 0e757ac..5d96817 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfVariables.java
+++ b/luni/src/main/java/libcore/reflect/ListOfVariables.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
 
 import java.lang.reflect.TypeVariable;
 import java.util.ArrayList;
 
-class ListOfVariables {
-    public static final TypeVariable[] EMPTY = new ImplForVariable[0];
+final class ListOfVariables {
+    public static final TypeVariable[] EMPTY = new TypeVariableImpl[0];
 
-    ArrayList<TypeVariable<?>> array = new ArrayList<TypeVariable<?>>();
+    final ArrayList<TypeVariable<?>> array = new ArrayList<TypeVariable<?>>();
 
     void add (TypeVariable<?> elem) {
         array.add(elem);
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForType.java b/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java
similarity index 89%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForType.java
rename to luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java
index b1f05d4..99dfe8b 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForType.java
+++ b/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java
@@ -14,21 +14,20 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
 
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 
-public final class ImplForType implements ParameterizedType {
+public final class ParameterizedTypeImpl implements ParameterizedType {
     private final ListOfTypes args;
-    private final ImplForType ownerType0; // Potentially unresolved.
+    private final ParameterizedTypeImpl ownerType0; // Potentially unresolved.
     private Type ownerTypeRes;
     private Class rawType; // Already resolved.
     private final String rawTypeName;
     private ClassLoader loader;
 
-
-    public ImplForType(ImplForType ownerType, String rawTypeName,
+    public ParameterizedTypeImpl(ParameterizedTypeImpl ownerType, String rawTypeName,
             ListOfTypes args, ClassLoader loader) {
         this.ownerType0 = ownerType;
         this.rawTypeName = rawTypeName;
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForVariable.java b/luni/src/main/java/libcore/reflect/TypeVariableImpl.java
similarity index 87%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForVariable.java
rename to luni/src/main/java/libcore/reflect/TypeVariableImpl.java
index 783d223..2eb9827 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForVariable.java
+++ b/luni/src/main/java/libcore/reflect/TypeVariableImpl.java
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
 
+import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.GenericDeclaration;
 import java.lang.reflect.Method;
@@ -23,8 +24,8 @@
 import java.lang.reflect.TypeVariable;
 
 
-public final class ImplForVariable<D extends GenericDeclaration> implements TypeVariable<D> {
-    private ImplForVariable<D> formalVar;
+public final class TypeVariableImpl<D extends GenericDeclaration> implements TypeVariable<D> {
+    private TypeVariableImpl<D> formalVar;
     private final GenericDeclaration declOfVarUser;
     private final String name;
     private D genericDeclaration;
@@ -51,7 +52,7 @@
      * @param name type variable name
      * @param bounds class and interface bounds
      */
-    ImplForVariable(D genericDecl, String name, ListOfTypes bounds) {
+    TypeVariableImpl(D genericDecl, String name, ListOfTypes bounds) {
         this.genericDeclaration = genericDecl;
         this.name = name;
         this.bounds = bounds;
@@ -63,7 +64,7 @@
      * @param genericDecl declaration where a type variable is used
      * @param name type variable name
      */
-    ImplForVariable(D genericDecl, String name) {
+    TypeVariableImpl(D genericDecl, String name) {
         this.name = name;
         this.declOfVarUser = genericDecl;
     }
@@ -83,11 +84,7 @@
         if (decl instanceof Class) {
             // FIXME: Is the following hierarchy correct?:
             Class cl = (Class)decl;
-            decl = cl.getEnclosingMethod();
-            if (decl != null) {
-                return decl;
-            }
-            decl = cl.getEnclosingConstructor();
+            decl = (GenericDeclaration) AnnotationAccess.getEnclosingMethodOrConstructor(cl);
             if (decl != null) {
                 return decl;
             }
@@ -113,7 +110,7 @@
                 throw new AssertionError("illegal type variable reference");
             }
         }
-        formalVar = (ImplForVariable<D>) var;
+        formalVar = (TypeVariableImpl<D>) var;
         this.genericDeclaration = formalVar.genericDeclaration;
         this.bounds = formalVar.bounds;
     }
diff --git a/luni/src/main/java/libcore/reflect/Types.java b/luni/src/main/java/libcore/reflect/Types.java
new file mode 100644
index 0000000..2132b11
--- /dev/null
+++ b/luni/src/main/java/libcore/reflect/Types.java
@@ -0,0 +1,167 @@
+/*
+ * 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.reflect;
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class Types {
+    private Types() {
+    }
+
+    // Holds a mapping from Java type names to native type codes.
+    private static final Map<Class<?>, String> PRIMITIVE_TO_SIGNATURE;
+    static {
+        PRIMITIVE_TO_SIGNATURE = new HashMap<Class<?>, String>(9);
+        PRIMITIVE_TO_SIGNATURE.put(byte.class, "B");
+        PRIMITIVE_TO_SIGNATURE.put(char.class, "C");
+        PRIMITIVE_TO_SIGNATURE.put(short.class, "S");
+        PRIMITIVE_TO_SIGNATURE.put(int.class, "I");
+        PRIMITIVE_TO_SIGNATURE.put(long.class, "J");
+        PRIMITIVE_TO_SIGNATURE.put(float.class, "F");
+        PRIMITIVE_TO_SIGNATURE.put(double.class, "D");
+        PRIMITIVE_TO_SIGNATURE.put(void.class, "V");
+        PRIMITIVE_TO_SIGNATURE.put(boolean.class, "Z");
+    }
+
+    public static Type[] getClonedTypeArray(ListOfTypes types) {
+        return types.getResolvedTypes().clone();
+    }
+
+    public static Type getType(Type type) {
+        if (type instanceof ParameterizedTypeImpl) {
+            return ((ParameterizedTypeImpl)type).getResolvedType();
+        } else {
+            return type;
+        }
+    }
+
+    /**
+     * Returns the internal name of {@code clazz} (also known as the descriptor).
+     */
+    public static String getSignature(Class<?> clazz) {
+        String primitiveSignature = PRIMITIVE_TO_SIGNATURE.get(clazz);
+        if (primitiveSignature != null) {
+            return primitiveSignature;
+        } else if (clazz.isArray()) {
+            return "[" + getSignature(clazz.getComponentType());
+        } else {
+            // TODO: this separates packages with '.' rather than '/'
+            return "L" + clazz.getName() + ";";
+        }
+    }
+
+    /**
+     * Returns the names of {@code types} separated by commas.
+     */
+    public static String toString(Class<?>[] types) {
+        if (types.length == 0) {
+            return "";
+        }
+        StringBuilder result = new StringBuilder();
+        appendTypeName(result, types[0]);
+        for (int i = 1; i < types.length; i++) {
+            result.append(',');
+            appendTypeName(result, types[i]);
+        }
+        return result.toString();
+    }
+
+    /**
+     * 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).
+     */
+    public static 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 {@code types} to {@code out} separated by commas.
+     */
+    public static void appendArrayGenericType(StringBuilder out, Type[] types) {
+        if (types.length == 0) {
+            return;
+        }
+        appendGenericType(out, types[0]);
+        for (int i = 1; i < types.length; i++) {
+            out.append(',');
+            appendGenericType(out, types[i]);
+        }
+    }
+
+    public static void appendGenericType(StringBuilder out, Type type) {
+        if (type instanceof TypeVariable) {
+            out.append(((TypeVariable) type).getName());
+        } else if (type instanceof ParameterizedType) {
+            out.append(type.toString());
+        } else if (type instanceof GenericArrayType) {
+            Type simplified = ((GenericArrayType) type).getGenericComponentType();
+            appendGenericType(out, simplified);
+            out.append("[]");
+        } else if (type instanceof Class) {
+            Class c = (Class<?>) type;
+            if (c.isArray()){
+                String as[] = c.getName().split("\\[");
+                int len = as.length-1;
+                if (as[len].length() > 1){
+                    out.append(as[len].substring(1, as[len].length() - 1));
+                } else {
+                    char ch = as[len].charAt(0);
+                    if (ch == 'I') {
+                        out.append("int");
+                    } else if (ch == 'B') {
+                        out.append("byte");
+                    } else if (ch == 'J') {
+                        out.append("long");
+                    } else if (ch == 'F') {
+                        out.append("float");
+                    } else if (ch == 'D') {
+                        out.append("double");
+                    } else if (ch == 'S') {
+                        out.append("short");
+                    } else if (ch == 'C') {
+                        out.append("char");
+                    } else if (ch == 'Z') {
+                        out.append("boolean");
+                    } else if (ch == 'V') {
+                        out.append("void");
+                    }
+                }
+                for (int i = 0; i < len; i++){
+                    out.append("[]");
+                }
+            } else {
+                out.append(c.getName());
+            }
+        }
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java b/luni/src/main/java/libcore/reflect/WildcardTypeImpl.java
similarity index 91%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java
rename to luni/src/main/java/libcore/reflect/WildcardTypeImpl.java
index b0605f2..97d2b26 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java
+++ b/luni/src/main/java/libcore/reflect/WildcardTypeImpl.java
@@ -14,18 +14,18 @@
  * limitations under the License.
  */
 
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
 
 import java.lang.reflect.MalformedParameterizedTypeException;
 import java.lang.reflect.Type;
 import java.lang.reflect.WildcardType;
 import java.util.Arrays;
 
-public final class ImplForWildcard implements WildcardType {
+public final class WildcardTypeImpl implements WildcardType {
 
     private final ListOfTypes extendsBound, superBound;
 
-    public ImplForWildcard(ListOfTypes extendsBound, ListOfTypes superBound) {
+    public WildcardTypeImpl(ListOfTypes extendsBound, ListOfTypes superBound) {
         this.extendsBound = extendsBound;
         this.superBound = superBound;
     }
diff --git a/luni/src/main/java/libcore/util/ZoneInfoDB.java b/luni/src/main/java/libcore/util/ZoneInfoDB.java
index b211c93..10e3900 100644
--- a/luni/src/main/java/libcore/util/ZoneInfoDB.java
+++ b/luni/src/main/java/libcore/util/ZoneInfoDB.java
@@ -21,7 +21,7 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.channels.FileChannel.MapMode;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -31,9 +31,6 @@
 import libcore.io.IoUtils;
 import libcore.io.MemoryMappedFile;
 
-// TODO: repackage this class, used by frameworks/base.
-import org.apache.harmony.luni.internal.util.TimezoneGetter;
-
 /**
  * A class used to initialize the time zone database. This implementation uses the
  * Olson tzdata as the source of time zone information. However, to conserve
@@ -43,185 +40,190 @@
  * @hide - used to implement TimeZone
  */
 public final class ZoneInfoDB {
-    private static final Object LOCK = new Object();
+  private static final TzData DATA =
+      new TzData(System.getenv("ANDROID_DATA") + "/misc/zoneinfo/tzdata",
+                 System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo/tzdata");
 
+  public static class TzData {
     /**
      * Rather than open, read, and close the big data file each time we look up a time zone,
      * we map the big data file during startup, and then just use the MemoryMappedFile.
      *
      * At the moment, this "big" data file is about 500 KiB. At some point, that will be small
-     * enough that we'll just keep the byte[] in memory.
+     * enough that we could just keep the byte[] in memory, but using mmap(2) like this has the
+     * nice property that even if someone replaces the file under us (because multiple gservices
+     * updates have gone out, say), we still get a consistent (if outdated) view of the world.
      */
-    private static final MemoryMappedFile TZDATA = mapData();
+    private MemoryMappedFile mappedFile;
 
-    private static String version;
-    private static String zoneTab;
+    private String version;
+    private String zoneTab;
 
     /**
      * The 'ids' array contains time zone ids sorted alphabetically, for binary searching.
      * The other two arrays are in the same order. 'byteOffsets' gives the byte offset
      * of each time zone, and 'rawUtcOffsets' gives the time zone's raw UTC offset.
      */
-    private static String[] ids;
-    private static int[] byteOffsets;
-    private static int[] rawUtcOffsets;
+    private String[] ids;
+    private int[] byteOffsets;
+    private int[] rawUtcOffsets;
 
-    static {
+    public TzData(String... paths) {
+      for (String path : paths) {
+        if (loadData(path)) {
+          return;
+        }
+      }
+
+      // We didn't find any usable tzdata on disk, so let's just hard-code knowledge of "GMT".
+      // This is actually implemented in TimeZone itself, so if this is the only time zone
+      // we report, we won't be asked any more questions.
+      System.logE("Couldn't find any tzdata!");
+      version = "missing";
+      zoneTab = "# Emergency fallback data.\n";
+      ids = new String[] { "GMT" };
+      byteOffsets = rawUtcOffsets = new int[1];
+    }
+
+    private boolean loadData(String path) {
+      try {
+        mappedFile = MemoryMappedFile.mmapRO(path);
+      } catch (ErrnoException errnoException) {
+        return false;
+      }
+      try {
         readHeader();
+        return true;
+      } catch (Exception ex) {
+        // Something's wrong with the file.
+        // Log the problem and return false so we try the next choice.
+        System.logE("tzdata file \"" + path + "\" was present but invalid!", ex);
+        return false;
+      }
     }
 
-    private ZoneInfoDB() {
+    private void readHeader() {
+      // byte[12] tzdata_version  -- "tzdata2012f\0"
+      // int index_offset
+      // int data_offset
+      // int zonetab_offset
+      BufferIterator it = mappedFile.bigEndianIterator();
+
+      byte[] tzdata_version = new byte[12];
+      it.readByteArray(tzdata_version, 0, tzdata_version.length);
+      String magic = new String(tzdata_version, 0, 6, StandardCharsets.US_ASCII);
+      if (!magic.equals("tzdata") || tzdata_version[11] != 0) {
+        throw new RuntimeException("bad tzdata magic: " + Arrays.toString(tzdata_version));
+      }
+      version = new String(tzdata_version, 6, 5, StandardCharsets.US_ASCII);
+
+      int index_offset = it.readInt();
+      int data_offset = it.readInt();
+      int zonetab_offset = it.readInt();
+
+      readIndex(it, index_offset, data_offset);
+      readZoneTab(it, zonetab_offset, (int) mappedFile.size() - zonetab_offset);
     }
 
-    private static void readHeader() {
-        // byte[12] tzdata_version  -- "tzdata2012f\0"
-        // int index_offset
-        // int data_offset
-        // int zonetab_offset
-        BufferIterator it = TZDATA.bigEndianIterator();
+    private void readZoneTab(BufferIterator it, int zoneTabOffset, int zoneTabSize) {
+      byte[] bytes = new byte[zoneTabSize];
+      it.seek(zoneTabOffset);
+      it.readByteArray(bytes, 0, bytes.length);
+      zoneTab = new String(bytes, 0, bytes.length, StandardCharsets.US_ASCII);
+    }
 
-        byte[] tzdata_version = new byte[12];
-        it.readByteArray(tzdata_version, 0, tzdata_version.length);
-        String magic = new String(tzdata_version, 0, 6, Charsets.US_ASCII);
-        if (!magic.equals("tzdata") || tzdata_version[11] != 0) {
-            throw new RuntimeException("bad tzdata magic: " + Arrays.toString(tzdata_version));
+    private void readIndex(BufferIterator it, int indexOffset, int dataOffset) {
+      it.seek(indexOffset);
+
+      // The database reserves 40 bytes for each id.
+      final int SIZEOF_TZNAME = 40;
+      // The database uses 32-bit (4 byte) integers.
+      final int SIZEOF_TZINT = 4;
+
+      byte[] idBytes = new byte[SIZEOF_TZNAME];
+      int indexSize = (dataOffset - indexOffset);
+      int entryCount = indexSize / (SIZEOF_TZNAME + 3*SIZEOF_TZINT);
+
+      char[] idChars = new char[entryCount * SIZEOF_TZNAME];
+      int[] idEnd = new int[entryCount];
+      int idOffset = 0;
+
+      byteOffsets = new int[entryCount];
+      rawUtcOffsets = new int[entryCount];
+
+      for (int i = 0; i < entryCount; i++) {
+        it.readByteArray(idBytes, 0, idBytes.length);
+
+        byteOffsets[i] = it.readInt();
+        byteOffsets[i] += dataOffset; // TODO: change the file format so this is included.
+
+        int length = it.readInt();
+        if (length < 44) {
+          throw new AssertionError("length in index file < sizeof(tzhead)");
         }
-        version = new String(tzdata_version, 6, 5, Charsets.US_ASCII);
+        rawUtcOffsets[i] = it.readInt();
 
-        int index_offset = it.readInt();
-        int data_offset = it.readInt();
-        int zonetab_offset = it.readInt();
-
-        readIndex(it, index_offset, data_offset);
-        readZoneTab(it, zonetab_offset);
-    }
-
-    private static MemoryMappedFile mapData() {
-        MemoryMappedFile result = mapData(System.getenv("ANDROID_DATA") + "/misc/zoneinfo/");
-        if (result == null) {
-            result = mapData(System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo/");
-            if (result == null) {
-                throw new AssertionError("Couldn't find any tzdata!");
-            }
-        }
-        return result;
-    }
-
-    private static MemoryMappedFile mapData(String directory) {
-        try {
-            return MemoryMappedFile.mmapRO(directory + "tzdata");
-        } catch (ErrnoException errnoException) {
-            return null;
-        }
-    }
-
-    private static void readZoneTab(BufferIterator it, int zoneTabOffset) {
-        byte[] bytes = new byte[(int) TZDATA.size() - zoneTabOffset];
-        it.seek(zoneTabOffset);
-        it.readByteArray(bytes, 0, bytes.length);
-        zoneTab = new String(bytes, 0, bytes.length, Charsets.US_ASCII);
-    }
-
-    private static void readIndex(BufferIterator it, int indexOffset, int dataOffset) {
-        it.seek(indexOffset);
-
-        // The database reserves 40 bytes for each id.
-        final int SIZEOF_TZNAME = 40;
-        // The database uses 32-bit (4 byte) integers.
-        final int SIZEOF_TZINT = 4;
-
-        byte[] idBytes = new byte[SIZEOF_TZNAME];
-        int indexSize = (dataOffset - indexOffset);
-        int entryCount = indexSize / (SIZEOF_TZNAME + 3*SIZEOF_TZINT);
-
-        char[] idChars = new char[entryCount * SIZEOF_TZNAME];
-        int[] idEnd = new int[entryCount];
-        int idOffset = 0;
-
-        byteOffsets = new int[entryCount];
-        rawUtcOffsets = new int[entryCount];
-
-        for (int i = 0; i < entryCount; i++) {
-            it.readByteArray(idBytes, 0, idBytes.length);
-
-            byteOffsets[i] = it.readInt();
-            byteOffsets[i] += dataOffset; // TODO: change the file format so this is included.
-
-            int length = it.readInt();
-            if (length < 44) {
-                throw new AssertionError("length in index file < sizeof(tzhead)");
-            }
-            rawUtcOffsets[i] = it.readInt();
-
-            // Don't include null chars in the String
-            int len = idBytes.length;
-            for (int j = 0; j < len; j++) {
-                if (idBytes[j] == 0) {
-                    break;
-                }
-                idChars[idOffset++] = (char) (idBytes[j] & 0xFF);
-            }
-
-            idEnd[i] = idOffset;
+        // Don't include null chars in the String
+        int len = idBytes.length;
+        for (int j = 0; j < len; j++) {
+          if (idBytes[j] == 0) {
+            break;
+          }
+          idChars[idOffset++] = (char) (idBytes[j] & 0xFF);
         }
 
-        // We create one string containing all the ids, and then break that into substrings.
-        // This way, all ids share a single char[] on the heap.
-        String allIds = new String(idChars, 0, idOffset);
-        ids = new String[entryCount];
-        for (int i = 0; i < entryCount; i++) {
-            ids[i] = allIds.substring(i == 0 ? 0 : idEnd[i - 1], idEnd[i]);
+        idEnd[i] = idOffset;
+      }
+
+      // We create one string containing all the ids, and then break that into substrings.
+      // This way, all ids share a single char[] on the heap.
+      String allIds = new String(idChars, 0, idOffset);
+      ids = new String[entryCount];
+      for (int i = 0; i < entryCount; i++) {
+        ids[i] = allIds.substring(i == 0 ? 0 : idEnd[i - 1], idEnd[i]);
+      }
+    }
+
+    public String[] getAvailableIDs() {
+      return ids.clone();
+    }
+
+    public String[] getAvailableIDs(int rawOffset) {
+      List<String> matches = new ArrayList<String>();
+      for (int i = 0, end = rawUtcOffsets.length; i < end; ++i) {
+        if (rawUtcOffsets[i] == rawOffset) {
+          matches.add(ids[i]);
         }
+      }
+      return matches.toArray(new String[matches.size()]);
     }
 
-    public static TimeZone makeTimeZone(String id) throws IOException {
-        // Work out where in the big data file this time zone is.
-        int index = Arrays.binarySearch(ids, id);
-        if (index < 0) {
-            return null;
-        }
-
-        BufferIterator it = TZDATA.bigEndianIterator();
-        it.skip(byteOffsets[index]);
-
-        return ZoneInfo.makeTimeZone(id, it);
+    public String getVersion() {
+      return version;
     }
 
-    public static String[] getAvailableIDs() {
-        return ids.clone();
+    public String getZoneTab() {
+      return zoneTab;
     }
 
-    public static String[] getAvailableIDs(int rawOffset) {
-        List<String> matches = new ArrayList<String>();
-        for (int i = 0, end = rawUtcOffsets.length; i < end; ++i) {
-            if (rawUtcOffsets[i] == rawOffset) {
-                matches.add(ids[i]);
-            }
-        }
-        return matches.toArray(new String[matches.size()]);
-    }
+    public TimeZone makeTimeZone(String id) throws IOException {
+      // Work out where in the big data file this time zone is.
+      int index = Arrays.binarySearch(ids, id);
+      if (index < 0) {
+        return null;
+      }
 
-    public static TimeZone getSystemDefault() {
-        synchronized (LOCK) {
-            TimezoneGetter tzGetter = TimezoneGetter.getInstance();
-            String zoneName = tzGetter != null ? tzGetter.getId() : null;
-            if (zoneName != null) {
-                zoneName = zoneName.trim();
-            }
-            if (zoneName == null || zoneName.isEmpty()) {
-                // use localtime for the simulator
-                // TODO: what does that correspond to?
-                zoneName = "localtime";
-            }
-            return TimeZone.getTimeZone(zoneName);
-        }
-    }
+      BufferIterator it = mappedFile.bigEndianIterator();
+      it.skip(byteOffsets[index]);
 
-    public static String getVersion() {
-        return version;
+      return ZoneInfo.makeTimeZone(id, it);
     }
+  }
 
-    public static String getZoneTab() {
-        return zoneTab;
-    }
+  private ZoneInfoDB() {
+  }
+
+  public static TzData getInstance() {
+    return DATA;
+  }
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/Types.java b/luni/src/main/java/org/apache/harmony/luni/lang/reflect/Types.java
deleted file mode 100644
index bd700fc..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/Types.java
+++ /dev/null
@@ -1,34 +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.luni.lang.reflect;
-
-import java.lang.reflect.Type;
-
-public class Types {
-
-    public static Type[] getClonedTypeArray(ListOfTypes types) {
-        return types.getResolvedTypes().clone();
-    }
-
-    public static Type getType(Type type) {
-        if (type instanceof ImplForType) {
-            return ((ImplForType)type).getResolvedType();
-        } else {
-            return type;
-        }
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
index 64d7ced..26097cf 100644
--- a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
+++ b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
@@ -23,7 +23,7 @@
 package org.apache.harmony.security.asn1;
 
 import java.io.IOException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.util.Locale;
 import java.util.TimeZone;
@@ -99,7 +99,7 @@
             temp = temp.substring(0, currLength);
         }
 
-        out.content = (temp + "Z").getBytes(Charsets.UTF_8);
+        out.content = (temp + "Z").getBytes(StandardCharsets.UTF_8);
         out.length = ((byte[]) out.content).length;
     }
 }
diff --git a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
index 024b65f..f7ea2bd 100644
--- a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
+++ b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
@@ -23,7 +23,7 @@
 package org.apache.harmony.security.asn1;
 
 import java.io.IOException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 
 /**
  * This class is the super class for all string ASN.1 types
@@ -39,12 +39,12 @@
 
         @Override
         public Object getDecodedObject(BerInputStream in) throws IOException {
-            return new String(in.buffer, in.contentOffset, in.length, Charsets.UTF_8);
+            return new String(in.buffer, in.contentOffset, in.length, StandardCharsets.UTF_8);
         }
 
         @Override
         public void setEncodingContent(BerOutputStream out) {
-            byte[] bytes = ((String) out.content).getBytes(Charsets.UTF_8);
+            byte[] bytes = ((String) out.content).getBytes(StandardCharsets.UTF_8);
             out.content = bytes;
             out.length = bytes.length;
         }
@@ -96,7 +96,7 @@
     public Object getDecodedObject(BerInputStream in) throws IOException {
         /* To ensure we get the correct encoding on non-ASCII platforms, specify
            that we wish to convert from ASCII to the default platform encoding */
-        return new String(in.buffer, in.contentOffset, in.length, Charsets.ISO_8859_1);
+        return new String(in.buffer, in.contentOffset, in.length, StandardCharsets.ISO_8859_1);
     }
 
     public void encodeASN(BerOutputStream out) {
@@ -109,7 +109,7 @@
     }
 
     public void setEncodingContent(BerOutputStream out) {
-        byte[] bytes = ((String) out.content).getBytes(Charsets.UTF_8);
+        byte[] bytes = ((String) out.content).getBytes(StandardCharsets.UTF_8);
         out.content = bytes;
         out.length = bytes.length;
     }
diff --git a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
index 7c355f8..a3e77d3 100644
--- a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
+++ b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
@@ -23,7 +23,7 @@
 package org.apache.harmony.security.asn1;
 
 import java.io.IOException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.text.SimpleDateFormat;
 import java.util.Locale;
 import java.util.TimeZone;
@@ -97,7 +97,7 @@
     @Override public void setEncodingContent(BerOutputStream out) {
         SimpleDateFormat sdf = new SimpleDateFormat(UTC_PATTERN, Locale.US);
         sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
-        out.content = sdf.format(out.content).getBytes(Charsets.UTF_8);
+        out.content = sdf.format(out.content).getBytes(StandardCharsets.UTF_8);
         out.length = ((byte[]) out.content).length;
     }
 }
diff --git a/luni/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java b/luni/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
index 4015e70..65782b2 100644
--- a/luni/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
+++ b/luni/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
@@ -112,11 +112,16 @@
         return authenticatedAttributes.getAttributes();
     }
 
+    /**
+     * Returns the non-IMPLICIT ASN.1 encoding of the "authAttrs" from this
+     * SignerInfo. That is, it will return as the encoding of a generic ASN.1
+     * SET.
+     */
     public byte[] getEncodedAuthenticatedAttributes() {
         if (authenticatedAttributes == null) {
             return null;
         }
-        return authenticatedAttributes.getEncoded();
+        return AuthenticatedAttributes.ASN1.encode(authenticatedAttributes.getAttributes());
     }
 
     public byte[] getEncryptedDigest() {
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java b/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
index 9453164..9129ec2 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
@@ -24,7 +24,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.security.cert.CRL;
 import java.security.cert.CRLException;
 import java.security.cert.CertPath;
@@ -432,8 +432,8 @@
     // ------------------------ Staff methods ------------------------------
     // ---------------------------------------------------------------------
 
-    private static final byte[] PEM_BEGIN = "-----BEGIN".getBytes(Charsets.UTF_8);
-    private static final byte[] PEM_END = "-----END".getBytes(Charsets.UTF_8);
+    private static final byte[] PEM_BEGIN = "-----BEGIN".getBytes(StandardCharsets.UTF_8);
+    private static final byte[] PEM_END = "-----END".getBytes(StandardCharsets.UTF_8);
     /**
      * Code describing free format for PEM boundary suffix:
      * "^-----BEGIN.*\n"         at the beginning, and<br>
@@ -445,7 +445,7 @@
      * "^-----BEGIN CERTIFICATE-----\n"   at the beginning, and<br>
      * "\n-----END CERTIFICATE-----"   at the end.
      */
-    private static final byte[] CERT_BOUND_SUFFIX = " CERTIFICATE-----".getBytes(Charsets.UTF_8);
+    private static final byte[] CERT_BOUND_SUFFIX = " CERTIFICATE-----".getBytes(StandardCharsets.UTF_8);
 
     /**
      * Method retrieves the PEM encoded data from the stream
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java b/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java
index 68bcec6..4600bdc 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java
@@ -48,7 +48,6 @@
 import org.apache.harmony.security.x509.Extension;
 import org.apache.harmony.security.x509.Extensions;
 import org.apache.harmony.security.x509.TBSCertificate;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider;
 
 /**
  * This class is an implementation of X509Certificate. It wraps
@@ -67,11 +66,11 @@
     /** the core object to be wrapped in X509Certificate */
     private final Certificate certificate;
 
+    private final TBSCertificate tbsCert;
+    private final Extensions extensions;
     // to speed up access to the info, the following fields
     // cache values retrieved from the certificate object,
     // initialized using the "single-check idiom".
-    private final TBSCertificate tbsCert;
-    private final Extensions extensions;
     private volatile long notBefore = -1;
     private volatile long notAfter = -1;
     private volatile BigInteger serialNumber;
@@ -369,12 +368,7 @@
             throws CertificateException, NoSuchAlgorithmException, InvalidKeyException,
             NoSuchProviderException, SignatureException {
 
-        Signature signature;
-        try {
-            signature = Signature.getInstance(getSigAlgName(), OpenSSLProvider.PROVIDER_NAME);
-        } catch (NoSuchAlgorithmException ignored) {
-            signature = Signature.getInstance(getSigAlgName());
-        }
+        Signature signature = Signature.getInstance(getSigAlgName());
         signature.initVerify(key);
         // retrieve the encoding of the TBSCertificate structure
         byte[] tbsCertificateLocal = getTbsCertificateInternal();
@@ -389,16 +383,7 @@
             throws CertificateException, NoSuchAlgorithmException, InvalidKeyException,
             NoSuchProviderException, SignatureException {
 
-        Signature signature;
-        try {
-            if (sigProvider == null) {
-                signature = Signature.getInstance(getSigAlgName(), OpenSSLProvider.PROVIDER_NAME);
-            } else {
-                signature = Signature.getInstance(getSigAlgName(), sigProvider);
-            }
-        } catch (NoSuchAlgorithmException ignored) {
-            signature = Signature.getInstance(getSigAlgName(), sigProvider);
-        }
+        Signature signature = Signature.getInstance(getSigAlgName(), sigProvider);
         signature.initVerify(key);
         // retrieve the encoding of the TBSCertificate structure
         byte[] tbsCertificateLocal = getTbsCertificateInternal();
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java
index 70a2449..7c2785a 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java
@@ -55,10 +55,8 @@
         put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
         put("Alg.Alias.MessageDigest.SHA", "SHA-1");
 
-        if (RandomBitsSupplier.isServiceAvailable()) {
-            put("SecureRandom.SHA1PRNG", SR_NAME);
-            put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
-        }
+        put("SecureRandom.SHA1PRNG", SR_NAME);
+        put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
 
         put("Signature.SHA1withDSA", SIGN_NAME);
         put("Signature.SHA1withDSA ImplementedIn", "Software");
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
deleted file mode 100644
index ad3a280..0000000
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You under the Apache License, Version 2.0
- *  (the "License"); you may not use this file except in compliance with
- *  the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-
-package org.apache.harmony.security.provider.crypto;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.security.ProviderException;
-import libcore.io.Streams;
-
-/**
- * Supplies random bits from /dev/urandom.
- */
-public class RandomBitsSupplier implements SHA1_Data {
-    private static FileInputStream devURandom;
-    static {
-        try {
-            devURandom = new FileInputStream(new File("/dev/urandom"));
-        } catch (IOException ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    static boolean isServiceAvailable() {
-        return (devURandom != null);
-    }
-
-    public static byte[] getRandomBits(int byteCount) {
-        if (byteCount <= 0) {
-            throw new IllegalArgumentException("Too few bytes requested: " + byteCount);
-        }
-        try {
-            byte[] result = new byte[byteCount];
-            Streams.readFully(devURandom, result, 0, byteCount);
-            return result;
-        } catch (Exception ex) {
-            throw new ProviderException("Couldn't read " + byteCount + " random bytes", ex);
-        }
-    }
-}
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Constants.java
similarity index 80%
rename from luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
rename to luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Constants.java
index b559576..fc6a847 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Constants.java
@@ -28,56 +28,55 @@
  * - a set of constant values, H0-H4, defined in "SECURE HASH STANDARD", FIPS PUB 180-2 ;<BR>
  * - implementation constant values to use in classes using SHA-1 algorithm.    <BR>
  */
+public final class SHA1Constants {
+    private SHA1Constants() {
+    }
 
-
-public interface SHA1_Data {
+    /**
+     *  constant defined in "SECURE HASH STANDARD"
+     */
+    public static final int H0 = 0x67452301;
 
 
     /**
      *  constant defined in "SECURE HASH STANDARD"
      */
-    static final int H0 = 0x67452301;
+    public static final int H1 = 0xEFCDAB89;
 
 
     /**
      *  constant defined in "SECURE HASH STANDARD"
      */
-    static final int H1 = 0xEFCDAB89;
+    public static final int H2 = 0x98BADCFE;
 
 
     /**
      *  constant defined in "SECURE HASH STANDARD"
      */
-    static final int H2 = 0x98BADCFE;
+    public static final int H3 = 0x10325476;
 
 
     /**
      *  constant defined in "SECURE HASH STANDARD"
      */
-    static final int H3 = 0x10325476;
-
-
-    /**
-     *  constant defined in "SECURE HASH STANDARD"
-     */
-    static final int H4 = 0xC3D2E1F0;
+    public static final int H4 = 0xC3D2E1F0;
 
 
     /**
      * offset in buffer to store number of bytes in 0-15 word frame
      */
-    static final int BYTES_OFFSET = 81;
+    public static final int BYTES_OFFSET = 81;
 
 
     /**
      * offset in buffer to store current hash value
      */
-    static final int HASH_OFFSET = 82;
+    public static final int HASH_OFFSET = 82;
 
 
     /**
      * # of bytes in H0-H4 words; <BR>
      * in this implementation # is set to 20 (in general # varies from 1 to 20)
      */
-    static final int DIGEST_LENGTH = 20;
+    public static final int DIGEST_LENGTH = 20;
 }
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java
index d42b901..57b9005 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java
@@ -22,6 +22,7 @@
 
 package org.apache.harmony.security.provider.crypto;
 
+import static org.apache.harmony.security.provider.crypto.SHA1Constants.*;
 
 /**
  * This class contains methods providing SHA-1 functionality to use in classes. <BR>
@@ -48,9 +49,7 @@
  * The resulting hash value replaces the previous hash value in the array;
  * original bits of the message are not preserved.
  */
-
-
-public class SHA1Impl implements SHA1_Data {
+public class SHA1Impl {
 
 
     /**
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
index 4d99d62..5c0e328 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
@@ -18,29 +18,41 @@
 
 package org.apache.harmony.security.provider.crypto;
 
+import dalvik.system.BlockGuard;
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.security.InvalidParameterException;
+import java.security.ProviderException;
 import java.security.SecureRandomSpi;
 import libcore.io.Streams;
 import libcore.util.EmptyArray;
 
-/**
- * This class extends the SecureRandomSpi class implementing all its abstract methods. <BR>
- * <BR>
- * To generate pseudo-random bits, the implementation uses technique described in
- * the "Random Number Generator (RNG) algorithms" section, Appendix A,
- * JavaTM Cryptography Architecture, API Specification&Reference <BR>
- * <BR>
- * The class implements the Serializable interface.
- */
+import static org.apache.harmony.security.provider.crypto.SHA1Constants.*;
 
-public class SHA1PRNG_SecureRandomImpl extends SecureRandomSpi implements Serializable, SHA1_Data {
+/**
+ * This class extends the SecureRandomSpi class implementing all its abstract methods.
+ *
+ * <p>To generate pseudo-random bits, the implementation uses technique described in
+ * the "Random Number Generator (RNG) algorithms" section, Appendix A,
+ * JavaTM Cryptography Architecture, API Specification & Reference.
+ */
+public class SHA1PRNG_SecureRandomImpl extends SecureRandomSpi implements Serializable {
 
     private static final long serialVersionUID = 283736797212159675L;
 
+    private static FileInputStream devURandom;
+    static {
+        try {
+            devURandom = new FileInputStream(new File("/dev/urandom"));
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
     // constants to use in expressions operating on bytes in int and long variables:
     // END_FLAGS - final bytes in words to append to message;
     //             see "ch.5.1 Padding the Message, FIPS 180-2"
@@ -241,7 +253,7 @@
 
         if (myRandom == null) {
             myRandom = new SHA1PRNG_SecureRandomImpl();
-            myRandom.engineSetSeed(RandomBitsSupplier.getRandomBits(DIGEST_LENGTH));
+            myRandom.engineSetSeed(getRandomBytes(DIGEST_LENGTH));
         }
 
         myBytes = new byte[numBytes];
@@ -285,7 +297,7 @@
         if (state == UNDEFINED) {
 
             // no seed supplied by user, hence it is generated thus randomizing internal state
-            updateSeed(RandomBitsSupplier.getRandomBits(DIGEST_LENGTH));
+            updateSeed(getRandomBytes(DIGEST_LENGTH));
             nextBIndex = HASHBYTES_TO_USE;
 
             // updateSeed(...) updates where the last word of the seed is, so we
@@ -531,4 +543,22 @@
         nextBIndex = ois.readInt();
         Streams.readFully(ois, nextBytes, nextBIndex, HASHBYTES_TO_USE - nextBIndex);
     }
+
+    private static byte[] getRandomBytes(int byteCount) {
+        if (byteCount <= 0) {
+            throw new IllegalArgumentException("Too few bytes requested: " + byteCount);
+        }
+
+        BlockGuard.Policy originalPolicy = BlockGuard.getThreadPolicy();
+        try {
+            BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
+            byte[] result = new byte[byteCount];
+            Streams.readFully(devURandom, result, 0, byteCount);
+            return result;
+        } catch (Exception ex) {
+            throw new ProviderException("Couldn't read " + byteCount + " random bytes", ex);
+        } finally {
+            BlockGuard.setThreadPolicy(originalPolicy);
+        }
+    }
 }
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java
index 71223b7..3f41f18 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java
@@ -18,20 +18,18 @@
 
 package org.apache.harmony.security.provider.crypto;
 
-
 import java.security.DigestException;
 import java.security.MessageDigestSpi;
 import java.util.Arrays;
 
+import static org.apache.harmony.security.provider.crypto.SHA1Constants.*;
 
 /**
  * This class extends the MessageDigestSpi class implementing all its abstract methods;
  * it overrides the "Object clone()" and "int engineGetDigestLength()" methods. <BR>
  * The class implements the Cloneable interface.
  */
-
-
-public class SHA1_MessageDigestImpl extends MessageDigestSpi implements Cloneable, SHA1_Data {
+public class SHA1_MessageDigestImpl extends MessageDigestSpi implements Cloneable {
     private int[] buffer;        // buffer has the following structure:
                                  // -  0-16 - frame for accumulating a message
                                  // - 17-79 - for SHA1Impl methods
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java b/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
index 465748e..9d01f8d 100644
--- a/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
+++ b/luni/src/main/java/org/apache/harmony/security/utils/AlgNameMapper.java
@@ -30,7 +30,6 @@
 import java.util.Map.Entry;
 import java.util.Set;
 import org.apache.harmony.security.asn1.ObjectIdentifier;
-import org.apache.harmony.xnet.provider.jsse.NativeCrypto;
 
 /**
  * Provides Algorithm Name to OID and OID to Algorithm Name mappings. Some known
@@ -114,12 +113,7 @@
      */
     public static String map2OID(String algName) {
         // alg2OidMap map contains upper case keys
-        final String result = alg2OidMap.get(algName.toUpperCase(Locale.US));
-        if (result != null) {
-            return result;
-        }
-
-        return NativeCrypto.OBJ_txt2nid_oid(algName);
+        return alg2OidMap.get(algName.toUpperCase(Locale.US));
     }
 
     /**
@@ -130,14 +124,12 @@
      */
     public static String map2AlgName(String oid) {
         // oid2AlgMap map contains upper case values
-        String algUC = oid2AlgMap.get(oid);
+        final String algUC = oid2AlgMap.get(oid);
         // if not null there is always map UC->Orig
         if (algUC != null) {
             return algAliasesMap.get(algUC);
         }
-
-        // If we don't know about this OID, ask OpenSSL if it does.
-        return NativeCrypto.OBJ_txt2nid_longName(oid);
+        return null;
     }
 
     /**
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
index f1d878d..135394d 100644
--- a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
+++ b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
@@ -36,13 +36,14 @@
 import java.util.LinkedList;
 import java.util.List;
 import javax.security.auth.x500.X500Principal;
+
+import org.apache.harmony.security.asn1.ASN1OctetString;
 import org.apache.harmony.security.asn1.BerInputStream;
 import org.apache.harmony.security.pkcs7.ContentInfo;
 import org.apache.harmony.security.pkcs7.SignedData;
 import org.apache.harmony.security.pkcs7.SignerInfo;
 import org.apache.harmony.security.provider.cert.X509CertImpl;
 import org.apache.harmony.security.x501.AttributeTypeAndValue;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider;
 
 public class JarUtils {
 
@@ -193,15 +194,37 @@
             byte[] existingDigest = null;
             for (AttributeTypeAndValue a : atr) {
                 if (Arrays.equals(a.getType().getOid(), MESSAGE_DIGEST_OID)) {
-//TODO value                    existingDigest = a.AttributeValue;
+                    if (existingDigest != null) {
+                        throw new SecurityException("Too many MessageDigest attributes");
+                    }
+                    Collection<?> entries = a.getValue().getValues(ASN1OctetString.getInstance());
+                    if (entries.size() != 1) {
+                        throw new SecurityException("Too many values for MessageDigest attribute");
+                    }
+                    existingDigest = (byte[]) entries.iterator().next();
                 }
             }
-            if (existingDigest != null) {
-                MessageDigest md = MessageDigest.getInstance(sigInfo.getDigestAlgorithm());
-                byte[] computedDigest = md.digest(sfBytes);
-                if (!Arrays.equals(existingDigest, computedDigest)) {
-                    throw new SecurityException("Incorrect MD");
-                }
+
+            // RFC 3852 section 9.2: it authAttrs is present, it must have a
+            // message digest entry.
+            if (existingDigest == null) {
+                throw new SecurityException("Missing MessageDigest in Authenticated Attributes");
+            }
+
+            MessageDigest md = null;
+            if (daOid != null) {
+                md = MessageDigest.getInstance(daOid);
+            }
+            if (md == null && daName != null) {
+                md = MessageDigest.getInstance(daName);
+            }
+            if (md == null) {
+                return null;
+            }
+
+            byte[] computedDigest = md.digest(sfBytes);
+            if (!Arrays.equals(existingDigest, computedDigest)) {
+                throw new SecurityException("Incorrect MD");
             }
         }
 
diff --git a/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java b/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
index 89f5b3e..3b5f622 100644
--- a/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
+++ b/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
@@ -23,7 +23,7 @@
 package org.apache.harmony.security.x501;
 
 import java.io.IOException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Locale;
@@ -68,7 +68,7 @@
             = new ObjectIdentifier(new int[] { 2, 5, 4, 3 }, "CN", RFC1779_NAMES);
 
     /** Domain component attribute (name from RFC 2253) */
-    private static final ObjectIdentifier DC = new ObjectIdentifier(
+    public static final ObjectIdentifier DC = new ObjectIdentifier(
             new int[] { 0, 9, 2342, 19200300, 100, 1, 25 }, "DC", RFC2253_NAMES);
 
     /** DN qualifier attribute (name from API spec) */
@@ -79,7 +79,7 @@
             = new ObjectIdentifier(new int[] { 2, 5, 4, 46 }, "DNQUALIFIER", RFC2459_NAMES);
 
     /** Email Address attribute (name from API spec) */
-    private static final ObjectIdentifier EMAILADDRESS = new ObjectIdentifier(
+    public static final ObjectIdentifier EMAILADDRESS = new ObjectIdentifier(
             new int[] { 1, 2, 840, 113549, 1, 9, 1}, "EMAILADDRESS", RFC2459_NAMES);
 
     /** Generation attribute (qualifies an individual's name) (name from API spec) */
@@ -179,6 +179,32 @@
         KNOWN_NAMES.putAll(RFC2459_NAMES);
     }
 
+    /**
+     * Parses OID string representation.
+     *
+     * @param sOid
+     *            string representation of OID
+     *
+     * @throws IOException
+     *             if OID can not be created from its string representation
+     */
+    public static ObjectIdentifier getObjectIdentifier(String sOid) throws IOException {
+        if (sOid.charAt(0) >= '0' && sOid.charAt(0) <= '9') {
+            int[] array = org.apache.harmony.security.asn1.ObjectIdentifier.toIntArray(sOid);
+            ObjectIdentifier thisOid = getOID(array);
+            if (thisOid == null) {
+                thisOid = new ObjectIdentifier(array);
+            }
+            return thisOid;
+
+        }
+        ObjectIdentifier thisOid = KNOWN_NAMES.get(sOid.toUpperCase(Locale.US));
+        if (thisOid == null) {
+            throw new IOException("Unrecognizable attribute name: " + sOid);
+        }
+        return thisOid;
+    }
+
     /** Attribute type */
     private final ObjectIdentifier oid;
 
@@ -196,31 +222,15 @@
     }
 
     /**
-     * Creates AttributeTypeAndValue with OID and AttributeValue. Parses OID
-     * string representation
+     * Creates AttributeTypeAndValue with OID and AttributeValue.
      *
-     * @param sOid
-     *            string representation of OID
+     * @param oid
+     *            object identifier
      * @param value
      *            attribute value
-     * @throws IOException
-     *             if OID can not be created from its string representation
      */
-    public AttributeTypeAndValue(String sOid, AttributeValue value) throws IOException {
-        if (sOid.charAt(0) >= '0' && sOid.charAt(0) <= '9') {
-            int[] array = org.apache.harmony.security.asn1.ObjectIdentifier.toIntArray(sOid);
-            ObjectIdentifier thisOid = getOID(array);
-            if (thisOid == null) {
-                thisOid = new ObjectIdentifier(array);
-            }
-            this.oid = thisOid;
-
-        } else {
-            this.oid = KNOWN_NAMES.get(sOid.toUpperCase(Locale.US));
-            if (this.oid == null) {
-                throw new IOException("Unrecognizable attribute name: " + sOid);
-            }
-        }
+    public AttributeTypeAndValue(ObjectIdentifier oid, AttributeValue value) throws IOException {
+        this.oid = oid;
         this.value = value;
     }
 
@@ -291,6 +301,10 @@
         return oid;
     }
 
+    public AttributeValue getValue() {
+        return value;
+    }
+
     /**
      * According to RFC 3280 (http://www.ietf.org/rfc/rfc3280.txt)
      * X.501 AttributeTypeAndValue structure is defined as follows:
@@ -368,7 +382,7 @@
                     av.bytes = (byte[]) out.content;
                     out.content = av;
                 } else {
-                    av.bytes = av.rawString.getBytes(Charsets.UTF_8);
+                    av.bytes = av.rawString.getBytes(StandardCharsets.UTF_8);
                     out.length = av.bytes.length;
                 }
             }
diff --git a/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java b/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
index 2369d0f..63be3f1 100644
--- a/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
+++ b/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
@@ -23,21 +23,25 @@
 package org.apache.harmony.security.x501;
 
 import java.io.IOException;
+import java.util.Collection;
+import org.apache.harmony.security.asn1.ASN1SetOf;
 import org.apache.harmony.security.asn1.ASN1StringType;
+import org.apache.harmony.security.asn1.ASN1Type;
 import org.apache.harmony.security.asn1.DerInputStream;
+import org.apache.harmony.security.utils.ObjectIdentifier;
 
 /**
  * X.501 Attribute Value
  */
 public final class AttributeValue {
 
-    public final boolean wasEncoded;
+    public boolean wasEncoded;
 
-    public String escapedString;
+    public final String escapedString;
 
     private String hexString;
 
-    private int tag = -1;
+    private final int tag;
 
     public byte[] encoded;
 
@@ -45,15 +49,26 @@
 
     public boolean hasQE; // raw string contains '"' or '\'
 
-    public String rawString;
+    public final String rawString;
 
-    public AttributeValue(String parsedString, boolean hasQorE) {
+    public AttributeValue(String parsedString, boolean hasQorE, ObjectIdentifier oid) {
         wasEncoded = false;
 
         this.hasQE = hasQorE;
-
         this.rawString = parsedString;
-        this.escapedString = makeEscaped(rawString);
+        this.escapedString = makeEscaped(rawString); // overwrites hasQE
+
+        int tag;
+        if (oid == AttributeTypeAndValue.EMAILADDRESS || oid == AttributeTypeAndValue.DC) {
+            // http://www.rfc-editor.org/rfc/rfc5280.txt
+            // says that EmailAddress and DomainComponent should be a IA5String
+            tag = ASN1StringType.IA5STRING.id;
+        } else if (isPrintableString(rawString)) {
+            tag = ASN1StringType.PRINTABLESTRING.id;
+        } else {
+            tag = ASN1StringType.UTF8STRING.id;
+        }
+        this.tag = tag;
     }
 
     public AttributeValue(String hexString, byte[] encoded) {
@@ -117,11 +132,6 @@
     }
 
     public int getTag() {
-        if (tag == -1) {
-            tag = isPrintableString(rawString)
-                    ? ASN1StringType.PRINTABLESTRING.id
-                    : ASN1StringType.UTF8STRING.id;
-        }
         return tag;
     }
 
@@ -129,9 +139,14 @@
         if (hexString == null) {
             if (!wasEncoded) {
                 //FIXME optimize me: what about reusable OutputStream???
-                encoded = isPrintableString(rawString)
-                        ? ASN1StringType.PRINTABLESTRING.encode(rawString)
-                        : ASN1StringType.UTF8STRING.encode(rawString);
+                if (tag == ASN1StringType.IA5STRING.id) {
+                    encoded = ASN1StringType.IA5STRING.encode(rawString);
+                } else if (tag == ASN1StringType.PRINTABLESTRING.id) {
+                    encoded = ASN1StringType.PRINTABLESTRING.encode(rawString);
+                } else {
+                    encoded = ASN1StringType.UTF8STRING.encode(rawString);
+                }
+                wasEncoded = true;
             }
 
             StringBuilder buf = new StringBuilder(encoded.length * 2 + 1);
@@ -157,6 +172,10 @@
         return hexString;
     }
 
+    public Collection<?> getValues(ASN1Type type) throws IOException {
+        return (Collection<?>) new ASN1SetOf(type).decode(encoded);
+    }
+
     public void appendQEString(StringBuilder sb) {
         sb.append('"');
         if (hasQE) {
diff --git a/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java b/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java
index 4946419..2f6fcb9 100644
--- a/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java
+++ b/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java
@@ -25,10 +25,10 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import org.apache.harmony.security.utils.ObjectIdentifier;
 import org.apache.harmony.security.x501.AttributeTypeAndValue;
 import org.apache.harmony.security.x501.AttributeValue;
 
-
 /**
  * Distinguished Name Parser.
  *
@@ -390,32 +390,33 @@
         if (attType == null) {
             return list; //empty list of RDNs
         }
+        ObjectIdentifier oid = AttributeTypeAndValue.getObjectIdentifier(attType);
 
         List<AttributeTypeAndValue> atav = new ArrayList<AttributeTypeAndValue>();
         while (true) {
             if (pos == chars.length) {
                 //empty Attribute Value
-                atav.add(new AttributeTypeAndValue(attType, new AttributeValue("", false)));
+                atav.add(new AttributeTypeAndValue(oid, new AttributeValue("", false, oid)));
                 list.add(0, atav);
                 return list;
             }
 
             switch (chars[pos]) {
             case '"':
-                atav.add(new AttributeTypeAndValue(attType, new AttributeValue(quotedAV(), hasQE)));
+                atav.add(new AttributeTypeAndValue(oid, new AttributeValue(quotedAV(), hasQE, oid)));
                 break;
             case '#':
-                atav.add(new AttributeTypeAndValue(attType, new AttributeValue(hexAV(), encoded)));
+                atav.add(new AttributeTypeAndValue(oid, new AttributeValue(hexAV(), encoded)));
                 break;
             case '+':
             case ',':
             case ';': // compatibility with RFC 1779: semicolon can separate RDNs
                 //empty attribute value
-                atav.add(new AttributeTypeAndValue(attType, new AttributeValue("", false)));
+                atav.add(new AttributeTypeAndValue(oid, new AttributeValue("", false, oid)));
                 break;
             default:
-                atav.add(new AttributeTypeAndValue(attType, new AttributeValue(
-                        escapedAV(), hasQE)));
+                atav.add(new AttributeTypeAndValue(oid,
+                                                   new AttributeValue(escapedAV(), hasQE, oid)));
             }
 
             if (pos >= chars.length) {
@@ -435,6 +436,7 @@
             if (attType == null) {
                 throw new IOException("Invalid distinguished name string");
             }
+            oid = AttributeTypeAndValue.getObjectIdentifier(attType);
         }
     }
 }
diff --git a/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java b/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java
index 9539054..92ff3a9 100644
--- a/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java
+++ b/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java
@@ -56,22 +56,31 @@
             "2.5.29.30", "2.5.29.36", "2.5.29.37", "2.5.29.54");
 
     // the values of extensions of the structure
-    private List<Extension> extensions;
-    private Set<String> critical;
-    private Set<String> noncritical;
+    private final List<Extension> extensions;
+
+    // to speed up access, the following fields cache values computed
+    // from the extensions field, initialized using the "single-check
+    // idiom".
+
+    private volatile Set<String> critical;
+    private volatile Set<String> noncritical;
     // the flag showing is there any unsupported critical extension
     // in the list of extensions or not.
-    private boolean hasUnsupported;
+    private volatile Boolean hasUnsupported;
+
     // map containing the oid of extensions as a keys and
     // Extension objects as values
-    private HashMap<String, Extension> oidMap;
+    private volatile HashMap<String, Extension> oidMap;
+
     // the ASN.1 encoded form of Extensions
     private byte[] encoding;
 
     /**
      * Constructs an object representing the value of Extensions.
      */
-    public Extensions() {}
+    public Extensions() {
+        this.extensions = null;
+    }
 
     public Extensions(List<Extension> extensions) {
         this.extensions = extensions;
@@ -85,27 +94,33 @@
      * Returns the list of critical extensions.
      */
     public Set<String> getCriticalExtensions() {
-        if (critical == null) {
+        Set<String> resultCritical = critical;
+        if (resultCritical == null) {
             makeOidsLists();
+            resultCritical = critical;
         }
-        return critical;
+        return resultCritical;
     }
 
     /**
      * Returns the list of critical extensions.
      */
     public Set<String> getNonCriticalExtensions() {
-        if (noncritical == null) {
+        Set<String> resultNoncritical = noncritical;
+        if (resultNoncritical == null) {
             makeOidsLists();
+            resultNoncritical = noncritical;
         }
-        return noncritical;
+        return resultNoncritical;
     }
 
     public boolean hasUnsupportedCritical() {
-        if (critical == null) {
+        Boolean resultHasUnsupported = hasUnsupported;
+        if (resultHasUnsupported == null) {
             makeOidsLists();
+            resultHasUnsupported = hasUnsupported;
         }
-        return hasUnsupported;
+        return resultHasUnsupported.booleanValue();
     }
 
     //
@@ -117,19 +132,23 @@
             return;
         }
         int size = extensions.size();
-        critical = new HashSet<String>(size);
-        noncritical = new HashSet<String>(size);
+        Set<String> localCritical = new HashSet<String>(size);
+        Set<String> localNoncritical = new HashSet<String>(size);
+        Boolean localHasUnsupported = Boolean.FALSE;
         for (Extension extension : extensions) {
             String oid = extension.getExtnID();
             if (extension.getCritical()) {
                 if (!SUPPORTED_CRITICAL.contains(oid)) {
-                    hasUnsupported = true;
+                    localHasUnsupported = Boolean.TRUE;
                 }
-                critical.add(oid);
+                localCritical.add(oid);
             } else {
-                noncritical.add(oid);
+                localNoncritical.add(oid);
             }
         }
+        this.critical = localCritical;
+        this.noncritical = localNoncritical;
+        this.hasUnsupported = localHasUnsupported;
     }
 
     /**
@@ -139,13 +158,15 @@
         if (extensions == null) {
             return null;
         }
-        if (oidMap == null) {
-            oidMap = new HashMap<String, Extension>();
+        HashMap<String, Extension> localOidMap = oidMap;
+        if (localOidMap == null) {
+            localOidMap = new HashMap<String, Extension>();
             for (Extension extension : extensions) {
-                oidMap.put(extension.getExtnID(), extension);
+                localOidMap.put(extension.getExtnID(), extension);
             }
+            this.oidMap = localOidMap;
         }
-        return oidMap.get(oid);
+        return localOidMap.get(oid);
     }
 
 
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java
deleted file mode 100644
index 59e20d6..0000000
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2010 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.xnet.provider.jsse;
-
-import java.security.Provider;
-
-/**
- * Provider that goes through OpenSSL for operations.
- * <p>
- * Every algorithm should have its IANA assigned OID as an alias. See the following URLs for each type:
- * <ul>
- * <li><a href="http://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml">Hash functions</a></li>
- * <li><a href="http://www.iana.org/assignments/dssc/dssc.xml">Signature algorithms</a></li>
- * <li><a href="http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html">NIST cryptographic algorithms</a></li>
- * </ul>
- */
-public final class OpenSSLProvider extends Provider {
-    public static final String PROVIDER_NAME = "AndroidOpenSSL";
-
-    public OpenSSLProvider() {
-        super(PROVIDER_NAME, 1.0, "Android's OpenSSL-backed security provider");
-
-        /* === SSL Contexts === */
-        put("SSLContext.SSL", OpenSSLContextImpl.class.getName());
-        put("SSLContext.SSLv3", OpenSSLContextImpl.class.getName());
-        put("SSLContext.TLS", OpenSSLContextImpl.class.getName());
-        put("SSLContext.TLSv1", OpenSSLContextImpl.class.getName());
-        put("SSLContext.TLSv1.1", OpenSSLContextImpl.class.getName());
-        put("SSLContext.TLSv1.2", OpenSSLContextImpl.class.getName());
-        put("SSLContext.Default", DefaultSSLContextImpl.class.getName());
-
-        /* === Message Digests === */
-        put("MessageDigest.SHA-1",
-            "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA1");
-        put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
-        put("Alg.Alias.MessageDigest.SHA", "SHA-1");
-        put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA-1");
-
-        put("MessageDigest.SHA-256",
-            "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA256");
-        put("Alg.Alias.MessageDigest.SHA256", "SHA-256");
-        put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256");
-
-        put("MessageDigest.SHA-384",
-            "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA384");
-        put("Alg.Alias.MessageDigest.SHA384", "SHA-384");
-        put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.2", "SHA-384");
-
-        put("MessageDigest.SHA-512",
-            "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA512");
-        put("Alg.Alias.MessageDigest.SHA512", "SHA-512");
-        put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512");
-
-        // iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) md5(5)
-        put("MessageDigest.MD5",
-            "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$MD5");
-        put("Alg.Alias.MessageDigest.1.2.840.113549.2.5", "MD5");
-
-        /* == KeyPairGenerators == */
-        put("KeyPairGenerator.RSA", OpenSSLRSAKeyPairGenerator.class.getName());
-        put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1.1", "RSA");
-
-        put("KeyPairGenerator.DSA", OpenSSLDSAKeyPairGenerator.class.getName());
-
-        put("KeyPairGenerator.EC", OpenSSLECKeyPairGenerator.class.getName());
-
-        /* == KeyFactory == */
-        put("KeyFactory.RSA", OpenSSLRSAKeyFactory.class.getName());
-        put("Alg.Alias.KeyFactory.1.2.840.113549.1.1.1", "RSA");
-
-        put("KeyFactory.DSA", OpenSSLDSAKeyFactory.class.getName());
-
-        put("KeyFactory.EC", OpenSSLECKeyFactory.class.getName());
-
-        /* == KeyAgreement == */
-        put("KeyAgreement.ECDH", OpenSSLECDHKeyAgreement.class.getName());
-
-        /* == Signatures == */
-        put("Signature.MD5WithRSA", OpenSSLSignature.MD5RSA.class.getName());
-        put("Alg.Alias.Signature.MD5WithRSAEncryption", "MD5WithRSA");
-        put("Alg.Alias.Signature.MD5/RSA", "MD5WithRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5WithRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.2.5with1.2.840.113549.1.1.1", "MD5WithRSA");
-
-        put("Signature.SHA1WithRSA", OpenSSLSignature.SHA1RSA.class.getName());
-        put("Alg.Alias.Signature.SHA1WithRSAEncryption", "SHA1WithRSA");
-        put("Alg.Alias.Signature.SHA1/RSA", "SHA1WithRSA");
-        put("Alg.Alias.Signature.SHA-1/RSA", "SHA1WithRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1WithRSA");
-        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.1", "SHA1WithRSA");
-        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.5", "SHA1WithRSA");
-        put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1WithRSA");
-
-        put("Signature.SHA256WithRSA", OpenSSLSignature.SHA256RSA.class.getName());
-        put("Alg.Alias.Signature.SHA256WithRSAEncryption", "SHA256WithRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256WithRSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.1",
-                "SHA256WithRSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.11",
-                "SHA256WithRSA");
-
-        put("Signature.SHA384WithRSA", OpenSSLSignature.SHA384RSA.class.getName());
-        put("Alg.Alias.Signature.SHA384WithRSAEncryption", "SHA384WithRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384WithRSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.113549.1.1.1",
-                "SHA384WithRSA");
-
-        put("Signature.SHA512WithRSA", OpenSSLSignature.SHA512RSA.class.getName());
-        put("Alg.Alias.Signature.SHA512WithRSAEncryption", "SHA512WithRSA");
-        put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512WithRSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.113549.1.1.1",
-                "SHA512WithRSA");
-
-        put("Signature.SHA1withDSA", OpenSSLSignature.SHA1DSA.class.getName());
-        put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
-        put("Alg.Alias.Signature.DSA", "SHA1withDSA");
-        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.1", "SHA1withDSA");
-        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.3", "SHA1withDSA");
-        put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA");
-        put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
-
-        put("Signature.NONEwithRSA", OpenSSLSignatureRawRSA.class.getName());
-
-        put("Signature.ECDSA", OpenSSLSignature.SHA1ECDSA.class.getName());
-        put("Alg.Alias.Signature.SHA1withECDSA", "ECDSA");
-        put("Alg.Alias.Signature.ECDSAwithSHA1", "ECDSA");
-        // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA1(1)
-        put("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA");
-        put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10045.2.1", "ECDSA");
-
-        // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA2(3)
-        put("Signature.SHA256withECDSA", OpenSSLSignature.SHA256ECDSA.class.getName());
-        // ecdsa-with-SHA256(2)
-        put("Alg.Alias.Signature.1.2.840.10045.4.3.2", "SHA256withECDSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.10045.2.1", "SHA256withECDSA");
-
-        put("Signature.SHA384withECDSA", OpenSSLSignature.SHA384ECDSA.class.getName());
-        // ecdsa-with-SHA384(3)
-        put("Alg.Alias.Signature.1.2.840.10045.4.3.3", "SHA384withECDSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.10045.2.1", "SHA384withECDSA");
-
-        put("Signature.SHA512withECDSA", OpenSSLSignature.SHA512ECDSA.class.getName());
-        // ecdsa-with-SHA512(4)
-        put("Alg.Alias.Signature.1.2.840.10045.4.3.4", "SHA512withECDSA");
-        put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.10045.2.1", "SHA512withECDSA");
-
-        /* === SecureRandom === */
-        /*
-         * We have to specify SHA1PRNG because various documentation mentions
-         * that algorithm by name instead of just recommending calling
-         * "new SecureRandom()"
-         */
-        put("SecureRandom.SHA1PRNG", OpenSSLRandom.class.getName());
-        put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
-
-        /* === Cipher === */
-        put("Cipher.RSA/ECB/NoPadding", OpenSSLCipherRSA.Raw.class.getName());
-        put("Alg.Alias.Cipher.RSA/None/NoPadding", "RSA/ECB/NoPadding");
-        put("Cipher.RSA/ECB/PKCS1Padding", OpenSSLCipherRSA.PKCS1.class.getName());
-        put("Alg.Alias.Cipher.RSA/None/PKCS1Padding", "RSA/ECB/PKCS1Padding");
-
-        /*
-         * OpenSSL only supports a subset of modes, so we'll name them
-         * explicitly here.
-         */
-        put("Cipher.AES/ECB/NoPadding", OpenSSLCipher.AES.ECB.NoPadding.class.getName());
-        put("Cipher.AES/ECB/PKCS5Padding", OpenSSLCipher.AES.ECB.PKCS5Padding.class.getName());
-        put("Cipher.AES/CBC/NoPadding", OpenSSLCipher.AES.CBC.NoPadding.class.getName());
-        put("Cipher.AES/CBC/PKCS5Padding", OpenSSLCipher.AES.CBC.PKCS5Padding.class.getName());
-        put("Cipher.AES/CFB/NoPadding", OpenSSLCipher.AES.CFB.NoPadding.class.getName());
-        put("Cipher.AES/CFB/PKCS5Padding", OpenSSLCipher.AES.CFB.PKCS5Padding.class.getName());
-        put("Cipher.AES/CTR/NoPadding", OpenSSLCipher.AES.CTR.NoPadding.class.getName());
-        put("Cipher.AES/CTR/PKCS5Padding", OpenSSLCipher.AES.CTR.PKCS5Padding.class.getName());
-        put("Cipher.AES/OFB/NoPadding", OpenSSLCipher.AES.OFB.NoPadding.class.getName());
-        put("Cipher.AES/OFB/PKCS5Padding", OpenSSLCipher.AES.OFB.PKCS5Padding.class.getName());
-
-        put("Cipher.DESEDE/CBC/NoPadding", OpenSSLCipher.DESEDE.CBC.NoPadding.class.getName());
-        put("Cipher.DESEDE/CBC/PKCS5Padding", OpenSSLCipher.DESEDE.CBC.PKCS5Padding.class.getName());
-        put("Cipher.DESEDE/CFB/NoPadding", OpenSSLCipher.DESEDE.CFB.NoPadding.class.getName());
-        put("Cipher.DESEDE/CFB/PKCS5Padding", OpenSSLCipher.DESEDE.CFB.PKCS5Padding.class.getName());
-        put("Cipher.DESEDE/ECB/NoPadding", OpenSSLCipher.DESEDE.ECB.NoPadding.class.getName());
-        put("Cipher.DESEDE/ECB/PKCS5Padding", OpenSSLCipher.DESEDE.ECB.PKCS5Padding.class.getName());
-        put("Cipher.DESEDE/OFB/NoPadding", OpenSSLCipher.DESEDE.OFB.NoPadding.class.getName());
-        put("Cipher.DESEDE/OFB/PKCS5Padding", OpenSSLCipher.DESEDE.OFB.PKCS5Padding.class.getName());
-
-        put("Cipher.ARC4", OpenSSLCipher.ARC4.class.getName());
-
-        /* === Mac === */
-
-        put("Mac.HmacMD5", OpenSSLMac.HmacMD5.class.getName());
-
-        // PKCS#2 - iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2)
-        // http://www.oid-info.com/get/1.2.840.113549.2
-
-        // HMAC-SHA-1 PRF (7)
-        put("Mac.HmacSHA1", OpenSSLMac.HmacSHA1.class.getName());
-        put("Alg.Alias.Mac.1.2.840.113549.2.7", "HmacSHA1");
-        put("Alg.Alias.Mac.HMAC-SHA1", "HmacSHA1");
-        put("Alg.Alias.Mac.HMAC/SHA1", "HmacSHA1");
-
-        // id-hmacWithSHA256 (9)
-        put("Mac.HmacSHA256", OpenSSLMac.HmacSHA256.class.getName());
-        put("Alg.Alias.Mac.1.2.840.113549.2.9", "HmacSHA256");
-        put("Alg.Alias.Mac.HMAC-SHA256", "HmacSHA256");
-        put("Alg.Alias.Mac.HMAC/SHA256", "HmacSHA256");
-
-        // id-hmacWithSHA384 (10)
-        put("Mac.HmacSHA384", OpenSSLMac.HmacSHA384.class.getName());
-        put("Alg.Alias.Mac.1.2.840.113549.2.10", "HmacSHA384");
-        put("Alg.Alias.Mac.HMAC-SHA384", "HmacSHA384");
-        put("Alg.Alias.Mac.HMAC/SHA384", "HmacSHA384");
-
-        // id-hmacWithSHA384 (11)
-        put("Mac.HmacSHA512", OpenSSLMac.HmacSHA512.class.getName());
-        put("Alg.Alias.Mac.1.2.840.113549.2.11", "HmacSHA512");
-        put("Alg.Alias.Mac.HMAC-SHA512", "HmacSHA512");
-        put("Alg.Alias.Mac.HMAC/SHA512", "HmacSHA512");
-
-        /* === Certificate === */
-
-        put("CertificateFactory.X509", OpenSSLX509CertificateFactory.class.getName());
-        put("Alg.Alias.CertificateFactory.X.509", "X509");
-    }
-}
diff --git a/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java b/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
index 54117bb..c4ff069 100644
--- a/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
+++ b/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
@@ -10,7 +10,7 @@
 import java.io.BufferedReader;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import org.xml.sax.SAXException;
 import org.xml.sax.XMLReader;
 
@@ -126,7 +126,7 @@
             in = loader.getResourceAsStream (service);
 
         if (in != null) {
-            reader = new BufferedReader (new InputStreamReader (in, Charsets.UTF_8));
+            reader = new BufferedReader (new InputStreamReader (in, StandardCharsets.UTF_8));
             className = reader.readLine ();
             in.close ();
         }
diff --git a/luni/src/main/native/ExecStrings.cpp b/luni/src/main/native/ExecStrings.cpp
new file mode 100644
index 0000000..a6a62e2
--- /dev/null
+++ b/luni/src/main/native/ExecStrings.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "ExecStrings"
+
+#include "ExecStrings.h"
+
+#include <stdlib.h>
+
+#include "cutils/log.h"
+#include "ScopedLocalRef.h"
+
+ExecStrings::ExecStrings(JNIEnv* env, jobjectArray java_string_array)
+    : env_(env), java_array_(java_string_array), array_(NULL) {
+  if (java_array_ == NULL) {
+    return;
+  }
+
+  jsize length = env_->GetArrayLength(java_array_);
+  array_ = new char*[length + 1];
+  array_[length] = NULL;
+  for (jsize i = 0; i < length; ++i) {
+    ScopedLocalRef<jstring> java_string(env_, reinterpret_cast<jstring>(env_->GetObjectArrayElement(java_array_, i)));
+    // We need to pass these strings to const-unfriendly code.
+    char* string = const_cast<char*>(env_->GetStringUTFChars(java_string.get(), NULL));
+    array_[i] = string;
+  }
+}
+
+ExecStrings::~ExecStrings() {
+  if (array_ == NULL) {
+    return;
+  }
+
+  // Temporarily clear any pending exception so we can clean up.
+  jthrowable pending_exception = env_->ExceptionOccurred();
+  if (pending_exception != NULL) {
+    env_->ExceptionClear();
+  }
+
+  jsize length = env_->GetArrayLength(java_array_);
+  for (jsize i = 0; i < length; ++i) {
+    ScopedLocalRef<jstring> java_string(env_, reinterpret_cast<jstring>(env_->GetObjectArrayElement(java_array_, i)));
+    env_->ReleaseStringUTFChars(java_string.get(), array_[i]);
+  }
+  delete[] array_;
+
+  // Re-throw any pending exception.
+  if (pending_exception != NULL) {
+    if (env_->Throw(pending_exception) < 0) {
+      ALOGE("Error rethrowing exception!");
+    }
+  }
+}
+
+char** ExecStrings::get() {
+  return array_;
+}
diff --git a/luni/src/main/native/ExecStrings.h b/luni/src/main/native/ExecStrings.h
new file mode 100644
index 0000000..f8a1b15
--- /dev/null
+++ b/luni/src/main/native/ExecStrings.h
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#include "jni.h"
+
+class ExecStrings {
+ public:
+  ExecStrings(JNIEnv* env, jobjectArray java_string_array);
+
+  ~ExecStrings();
+
+  char** get();
+
+ private:
+  JNIEnv* env_;
+  jobjectArray java_array_;
+  char** array_;
+
+  // Disallow copy and assignment.
+  ExecStrings(const ExecStrings&);
+  void operator=(const ExecStrings&);
+};
diff --git a/luni/src/main/native/IcuUtilities.h b/luni/src/main/native/IcuUtilities.h
index 219d663..d93282c 100644
--- a/luni/src/main/native/IcuUtilities.h
+++ b/luni/src/main/native/IcuUtilities.h
@@ -17,6 +17,8 @@
 #ifndef ICU_UTILITIES_H_included
 #define ICU_UTILITIES_H_included
 
+#define U_HAVE_STD_STRING 1 // For UnicodeString::toUTF8String(std::string&).
+
 #include "jni.h"
 #include "unicode/utypes.h" // For UErrorCode.
 #include "unicode/locid.h" // For Locale.
diff --git a/luni/src/main/native/JniConstants.cpp b/luni/src/main/native/JniConstants.cpp
deleted file mode 100644
index 8693cf5..0000000
--- a/luni/src/main/native/JniConstants.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "JniConstants.h"
-#include "ScopedLocalRef.h"
-
-#include <stdlib.h>
-
-jclass JniConstants::bidiRunClass;
-jclass JniConstants::bigDecimalClass;
-jclass JniConstants::booleanClass;
-jclass JniConstants::byteArrayClass;
-jclass JniConstants::byteClass;
-jclass JniConstants::calendarClass;
-jclass JniConstants::charsetICUClass;
-jclass JniConstants::constructorClass;
-jclass JniConstants::deflaterClass;
-jclass JniConstants::doubleClass;
-jclass JniConstants::errnoExceptionClass;
-jclass JniConstants::fieldClass;
-jclass JniConstants::fieldPositionIteratorClass;
-jclass JniConstants::fileDescriptorClass;
-jclass JniConstants::gaiExceptionClass;
-jclass JniConstants::inet6AddressClass;
-jclass JniConstants::inetAddressClass;
-jclass JniConstants::inetSocketAddressClass;
-jclass JniConstants::inetUnixAddressClass;
-jclass JniConstants::inflaterClass;
-jclass JniConstants::inputStreamClass;
-jclass JniConstants::integerClass;
-jclass JniConstants::localeDataClass;
-jclass JniConstants::longClass;
-jclass JniConstants::methodClass;
-jclass JniConstants::mutableIntClass;
-jclass JniConstants::mutableLongClass;
-jclass JniConstants::objectClass;
-jclass JniConstants::objectArrayClass;
-jclass JniConstants::outputStreamClass;
-jclass JniConstants::parsePositionClass;
-jclass JniConstants::patternSyntaxExceptionClass;
-jclass JniConstants::realToStringClass;
-jclass JniConstants::socketClass;
-jclass JniConstants::socketImplClass;
-jclass JniConstants::stringClass;
-jclass JniConstants::structAddrinfoClass;
-jclass JniConstants::structFlockClass;
-jclass JniConstants::structGroupReqClass;
-jclass JniConstants::structLingerClass;
-jclass JniConstants::structPasswdClass;
-jclass JniConstants::structPollfdClass;
-jclass JniConstants::structStatClass;
-jclass JniConstants::structStatFsClass;
-jclass JniConstants::structTimevalClass;
-jclass JniConstants::structUcredClass;
-jclass JniConstants::structUtsnameClass;
-
-static jclass findClass(JNIEnv* env, const char* name) {
-    ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
-    jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
-    if (result == NULL) {
-        ALOGE("failed to find class '%s'", name);
-        abort();
-    }
-    return result;
-}
-
-void JniConstants::init(JNIEnv* env) {
-    bidiRunClass = findClass(env, "java/text/Bidi$Run");
-    bigDecimalClass = findClass(env, "java/math/BigDecimal");
-    booleanClass = findClass(env, "java/lang/Boolean");
-    byteClass = findClass(env, "java/lang/Byte");
-    byteArrayClass = findClass(env, "[B");
-    calendarClass = findClass(env, "java/util/Calendar");
-    charsetICUClass = findClass(env, "java/nio/charset/CharsetICU");
-    constructorClass = findClass(env, "java/lang/reflect/Constructor");
-    deflaterClass = findClass(env, "java/util/zip/Deflater");
-    doubleClass = findClass(env, "java/lang/Double");
-    errnoExceptionClass = findClass(env, "libcore/io/ErrnoException");
-    fieldClass = findClass(env, "java/lang/reflect/Field");
-    fieldPositionIteratorClass = findClass(env, "libcore/icu/NativeDecimalFormat$FieldPositionIterator");
-    fileDescriptorClass = findClass(env, "java/io/FileDescriptor");
-    gaiExceptionClass = findClass(env, "libcore/io/GaiException");
-    inet6AddressClass = findClass(env, "java/net/Inet6Address");
-    inetAddressClass = findClass(env, "java/net/InetAddress");
-    inetSocketAddressClass = findClass(env, "java/net/InetSocketAddress");
-    inetUnixAddressClass = findClass(env, "java/net/InetUnixAddress");
-    inflaterClass = findClass(env, "java/util/zip/Inflater");
-    inputStreamClass = findClass(env, "java/io/InputStream");
-    integerClass = findClass(env, "java/lang/Integer");
-    localeDataClass = findClass(env, "libcore/icu/LocaleData");
-    longClass = findClass(env, "java/lang/Long");
-    methodClass = findClass(env, "java/lang/reflect/Method");
-    mutableIntClass = findClass(env, "libcore/util/MutableInt");
-    mutableLongClass = findClass(env, "libcore/util/MutableLong");
-    objectClass = findClass(env, "java/lang/Object");
-    objectArrayClass = findClass(env, "[Ljava/lang/Object;");
-    outputStreamClass = findClass(env, "java/io/OutputStream");
-    parsePositionClass = findClass(env, "java/text/ParsePosition");
-    patternSyntaxExceptionClass = findClass(env, "java/util/regex/PatternSyntaxException");
-    realToStringClass = findClass(env, "java/lang/RealToString");
-    socketClass = findClass(env, "java/net/Socket");
-    socketImplClass = findClass(env, "java/net/SocketImpl");
-    stringClass = findClass(env, "java/lang/String");
-    structAddrinfoClass = findClass(env, "libcore/io/StructAddrinfo");
-    structFlockClass = findClass(env, "libcore/io/StructFlock");
-    structGroupReqClass = findClass(env, "libcore/io/StructGroupReq");
-    structLingerClass = findClass(env, "libcore/io/StructLinger");
-    structPasswdClass = findClass(env, "libcore/io/StructPasswd");
-    structPollfdClass = findClass(env, "libcore/io/StructPollfd");
-    structStatClass = findClass(env, "libcore/io/StructStat");
-    structStatFsClass = findClass(env, "libcore/io/StructStatFs");
-    structTimevalClass = findClass(env, "libcore/io/StructTimeval");
-    structUcredClass = findClass(env, "libcore/io/StructUcred");
-    structUtsnameClass = findClass(env, "libcore/io/StructUtsname");
-}
diff --git a/luni/src/main/native/JniConstants.h b/luni/src/main/native/JniConstants.h
deleted file mode 100644
index 8fd7bc8..0000000
--- a/luni/src/main/native/JniConstants.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2010 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 JNI_CONSTANTS_H_included
-#define JNI_CONSTANTS_H_included
-
-#include "JNIHelp.h"
-
-/**
- * A cache to avoid calling FindClass at runtime.
- *
- * Class lookup is relatively expensive (2.5us on passion-eng at the time of writing), so we do
- * all such lookups eagerly at VM startup. This means that code that never uses, say,
- * java.util.zip.Deflater still has to pay for the lookup, but it means that on a device the cost
- * is definitely paid during boot and amortized. A central cache also removes the temptation to
- * dynamically call FindClass rather than add a small cache to each file that needs one. Another
- * cost is that each class cached here requires a global reference, though in practice we save
- * enough by not having a global reference for each file that uses a class such as java.lang.String
- * which is used in several files.
- *
- * FindClass is still called in a couple of situations: when throwing exceptions, and in some of
- * the serialization code. The former is clearly not a performance case, and we're currently
- * assuming that neither is the latter.
- *
- * TODO: similar arguments hold for field and method IDs; we should cache them centrally too.
- */
-struct JniConstants {
-    static void init(JNIEnv* env);
-
-    static jclass bidiRunClass;
-    static jclass bigDecimalClass;
-    static jclass booleanClass;
-    static jclass byteArrayClass;
-    static jclass byteClass;
-    static jclass calendarClass;
-    static jclass charsetICUClass;
-    static jclass constructorClass;
-    static jclass deflaterClass;
-    static jclass doubleClass;
-    static jclass errnoExceptionClass;
-    static jclass fieldClass;
-    static jclass fieldPositionIteratorClass;
-    static jclass fileDescriptorClass;
-    static jclass gaiExceptionClass;
-    static jclass inet6AddressClass;
-    static jclass inetAddressClass;
-    static jclass inetSocketAddressClass;
-    static jclass inetUnixAddressClass;
-    static jclass inflaterClass;
-    static jclass inputStreamClass;
-    static jclass integerClass;
-    static jclass localeDataClass;
-    static jclass longClass;
-    static jclass methodClass;
-    static jclass mutableIntClass;
-    static jclass mutableLongClass;
-    static jclass objectClass;
-    static jclass objectArrayClass;
-    static jclass outputStreamClass;
-    static jclass parsePositionClass;
-    static jclass patternSyntaxExceptionClass;
-    static jclass realToStringClass;
-    static jclass socketClass;
-    static jclass socketImplClass;
-    static jclass stringClass;
-    static jclass structAddrinfoClass;
-    static jclass structFlockClass;
-    static jclass structGroupReqClass;
-    static jclass structLingerClass;
-    static jclass structPasswdClass;
-    static jclass structPollfdClass;
-    static jclass structStatClass;
-    static jclass structStatFsClass;
-    static jclass structTimevalClass;
-    static jclass structUcredClass;
-    static jclass structUtsnameClass;
-};
-
-#define NATIVE_METHOD(className, functionName, signature) \
-    { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
-
-#endif  // JNI_CONSTANTS_H_included
diff --git a/luni/src/main/native/Portability.h b/luni/src/main/native/Portability.h
index 833d5bb..60b7062 100644
--- a/luni/src/main/native/Portability.h
+++ b/luni/src/main/native/Portability.h
@@ -72,9 +72,7 @@
 
 #include <byteswap.h>
 #include <sys/sendfile.h>
-
-// For statfs(3).
-#include <sys/vfs.h> // Bionic doesn't have <sys/statvfs.h>
+#include <sys/statvfs.h>
 
 #endif
 
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index c94cd5d..54aecef 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -31,13 +31,13 @@
 
     ScopedLocalFrame localFrame(env);
 
-    JniConstants::init(env);
-
 #define REGISTER(FN) extern void FN(JNIEnv*); FN(env)
     REGISTER(register_java_io_Console);
     REGISTER(register_java_io_File);
     REGISTER(register_java_io_ObjectStreamClass);
     REGISTER(register_java_lang_Character);
+    REGISTER(register_java_lang_Double);
+    REGISTER(register_java_lang_Float);
     REGISTER(register_java_lang_Math);
     REGISTER(register_java_lang_ProcessManager);
     REGISTER(register_java_lang_RealToString);
@@ -55,6 +55,7 @@
     REGISTER(register_java_util_zip_Deflater);
     REGISTER(register_java_util_zip_Inflater);
     REGISTER(register_libcore_icu_AlphabeticIndex);
+    REGISTER(register_libcore_icu_DateIntervalFormat);
     REGISTER(register_libcore_icu_ICU);
     REGISTER(register_libcore_icu_NativeBreakIterator);
     REGISTER(register_libcore_icu_NativeCollation);
@@ -72,7 +73,7 @@
     REGISTER(register_libcore_net_RawSocket);
     REGISTER(register_org_apache_harmony_dalvik_NativeTestTarget);
     REGISTER(register_org_apache_harmony_xml_ExpatParser);
-    REGISTER(register_org_apache_harmony_xnet_provider_jsse_NativeCrypto);
+    REGISTER(register_org_conscrypt_NativeCrypto);
     REGISTER(register_sun_misc_Unsafe);
 #undef REGISTER
     return JNI_VERSION_1_6;
diff --git a/luni/src/main/native/java_lang_Character.cpp b/luni/src/main/native/java_lang_Character.cpp
index 7dbef90..de1800e 100644
--- a/luni/src/main/native/java_lang_Character.cpp
+++ b/luni/src/main/native/java_lang_Character.cpp
@@ -135,6 +135,14 @@
     return ublock_getCode(codePoint);
 }
 
+static jboolean Character_isAlphabetic(JNIEnv*, jclass, jint codePoint) {
+  return u_hasBinaryProperty(codePoint, UCHAR_ALPHABETIC);
+}
+
+static jboolean Character_isIdeographic(JNIEnv*, jclass, jint codePoint) {
+  return u_hasBinaryProperty(codePoint, UCHAR_IDEOGRAPHIC);
+}
+
 static JNINativeMethod gMethods[] = {
     NATIVE_METHOD(Character, digitImpl, "!(II)I"),
     NATIVE_METHOD(Character, forNameImpl, "(Ljava/lang/String;)I"),
@@ -142,9 +150,11 @@
     NATIVE_METHOD(Character, getNameImpl, "(I)Ljava/lang/String;"),
     NATIVE_METHOD(Character, getNumericValueImpl, "!(I)I"),
     NATIVE_METHOD(Character, getTypeImpl, "!(I)I"),
+    NATIVE_METHOD(Character, isAlphabetic, "!(I)Z"),
     NATIVE_METHOD(Character, isDefinedImpl, "!(I)Z"),
     NATIVE_METHOD(Character, isDigitImpl, "!(I)Z"),
     NATIVE_METHOD(Character, isIdentifierIgnorableImpl, "!(I)Z"),
+    NATIVE_METHOD(Character, isIdeographic, "!(I)Z"),
     NATIVE_METHOD(Character, isLetterImpl, "!(I)Z"),
     NATIVE_METHOD(Character, isLetterOrDigitImpl, "!(I)Z"),
     NATIVE_METHOD(Character, isLowerCaseImpl, "!(I)Z"),
diff --git a/luni/src/main/native/java_lang_Double.cpp b/luni/src/main/native/java_lang_Double.cpp
new file mode 100644
index 0000000..259be30
--- /dev/null
+++ b/luni/src/main/native/java_lang_Double.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "Double"
+
+#include "JNIHelp.h"
+#include "JniConstants.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+union Double {
+    uint64_t bits;
+    double d;
+};
+
+static const jlong NaN = 0x7ff8000000000000ULL;
+
+static jlong Double_doubleToLongBits(JNIEnv*, jclass, jdouble val) {
+    Double d;
+    d.d = val;
+    //  For this method all values in the NaN range are normalized to the canonical NaN value.
+    return isnan(d.d) ? NaN : d.bits;
+}
+
+static jlong Double_doubleToRawLongBits(JNIEnv*, jclass, jdouble val) {
+    Double d;
+    d.d = val;
+    return d.bits;
+}
+
+static jdouble Double_longBitsToDouble(JNIEnv*, jclass, jlong val) {
+    Double d;
+    d.bits = val;
+    return d.d;
+}
+
+static JNINativeMethod gMethods[] = {
+    NATIVE_METHOD(Double, doubleToLongBits, "(D)J"),
+    NATIVE_METHOD(Double, doubleToRawLongBits, "(D)J"),
+    NATIVE_METHOD(Double, longBitsToDouble, "(J)D"),
+};
+int register_java_lang_Double(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "java/lang/Double", gMethods, NELEM(gMethods));
+}
diff --git a/luni/src/main/native/java_lang_Float.cpp b/luni/src/main/native/java_lang_Float.cpp
new file mode 100644
index 0000000..59544db
--- /dev/null
+++ b/luni/src/main/native/java_lang_Float.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "Float"
+
+#include "JNIHelp.h"
+#include "JniConstants.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+union Float {
+    unsigned int bits;
+    float f;
+};
+
+static const jint NaN = 0x7fc00000;
+
+static jint Float_floatToIntBits(JNIEnv*, jclass, jfloat val) {
+    Float f;
+    f.f = val;
+    //  For this method all values in the NaN range are normalized to the canonical NaN value.
+    return isnanf(f.f) ? NaN : f.bits;
+}
+
+jint Float_floatToRawIntBits(JNIEnv*, jclass, jfloat val) {
+    Float f;
+    f.f = val;
+    return f.bits;
+}
+
+jfloat Float_intBitsToFloat(JNIEnv*, jclass, jint val) {
+    Float f;
+    f.bits = val;
+    return f.f;
+}
+
+static JNINativeMethod gMethods[] = {
+    NATIVE_METHOD(Float, floatToIntBits, "(F)I"),
+    NATIVE_METHOD(Float, floatToRawIntBits, "(F)I"),
+    NATIVE_METHOD(Float, intBitsToFloat, "(I)F"),
+};
+int register_java_lang_Float(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "java/lang/Float", gMethods, NELEM(gMethods));
+}
diff --git a/luni/src/main/native/java_lang_Math.cpp b/luni/src/main/native/java_lang_Math.cpp
index 273820e..784b84d 100644
--- a/luni/src/main/native/java_lang_Math.cpp
+++ b/luni/src/main/native/java_lang_Math.cpp
@@ -23,6 +23,14 @@
 #include <stdlib.h>
 #include <math.h>
 
+static jdouble Math_sin(JNIEnv*, jclass, jdouble a) {
+    return sin(a);
+}
+
+static jdouble Math_cos(JNIEnv*, jclass, jdouble a) {
+    return cos(a);
+}
+
 static jdouble Math_tan(JNIEnv*, jclass, jdouble a) {
     return tan(a);
 }
@@ -91,6 +99,10 @@
     return cbrt(a);
 }
 
+static jdouble Math_sqrt(JNIEnv*, jclass, jdouble a) {
+    return sqrt(a);
+}
+
 static jdouble Math_expm1(JNIEnv*, jclass, jdouble a) {
     return expm1(a);
 }
@@ -115,6 +127,7 @@
     NATIVE_METHOD(Math, atan2, "!(DD)D"),
     NATIVE_METHOD(Math, cbrt, "!(D)D"),
     NATIVE_METHOD(Math, ceil, "!(D)D"),
+    NATIVE_METHOD(Math, cos, "!(D)D"),
     NATIVE_METHOD(Math, cosh, "!(D)D"),
     NATIVE_METHOD(Math, exp, "!(D)D"),
     NATIVE_METHOD(Math, expm1, "!(D)D"),
@@ -126,7 +139,9 @@
     NATIVE_METHOD(Math, nextafter, "!(DD)D"),
     NATIVE_METHOD(Math, pow, "!(DD)D"),
     NATIVE_METHOD(Math, rint, "!(D)D"),
+    NATIVE_METHOD(Math, sin, "!(D)D"),
     NATIVE_METHOD(Math, sinh, "!(D)D"),
+    NATIVE_METHOD(Math, sqrt, "!(D)D"),
     NATIVE_METHOD(Math, tan, "!(D)D"),
     NATIVE_METHOD(Math, tanh, "!(D)D"),
 };
diff --git a/luni/src/main/native/java_lang_ProcessManager.cpp b/luni/src/main/native/java_lang_ProcessManager.cpp
index e3f0f45..a74ba8b 100644
--- a/luni/src/main/native/java_lang_ProcessManager.cpp
+++ b/luni/src/main/native/java_lang_ProcessManager.cpp
@@ -16,223 +16,222 @@
 
 #define LOG_TAG "ProcessManager"
 
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
 
+#include "cutils/log.h"
 #include "jni.h"
+#include "ExecStrings.h"
 #include "JNIHelp.h"
 #include "JniConstants.h"
 #include "Portability.h"
 #include "ScopedLocalRef.h"
-#include "cutils/log.h"
 #include "toStringArray.h"
 
-/** Close all open fds > 2 (i.e. everything but stdin/out/err), != skipFd. */
-static void closeNonStandardFds(int skipFd1, int skipFd2) {
-    // TODO: rather than close all these non-open files, we could look in /proc/self/fd.
-    rlimit rlimit;
-    getrlimit(RLIMIT_NOFILE, &rlimit);
-    const int max_fd = rlimit.rlim_max;
-    for (int fd = 3; fd < max_fd; ++fd) {
-        if (fd != skipFd1 && fd != skipFd2) {
-            close(fd);
-        }
+static void CloseNonStandardFds(int status_pipe_fd) {
+  // On Cygwin, Linux, and Solaris, the best way to close iterates over "/proc/self/fd/".
+  const char* fd_path = "/proc/self/fd";
+#ifdef __APPLE__
+  // On Mac OS, there's "/dev/fd/" which Linux seems to link to "/proc/self/fd/",
+  // but which on Solaris appears to be something quite different.
+  fd_path = "/dev/fd";
+#endif
+
+  // Keep track of the system properties fd so we don't close it.
+  int properties_fd = -1;
+  char* properties_fd_string = getenv("ANDROID_PROPERTY_WORKSPACE");
+  if (properties_fd_string != NULL) {
+    properties_fd = atoi(properties_fd_string);
+  }
+
+  DIR* d = opendir(fd_path);
+  int dir_fd = dirfd(d);
+  dirent* e;
+  while ((e = readdir(d)) != NULL) {
+    char* end;
+    int fd = strtol(e->d_name, &end, 10);
+    if (!*end) {
+      if (fd > STDERR_FILENO && fd != dir_fd && fd != status_pipe_fd && fd != properties_fd) {
+        close(fd);
+      }
     }
+  }
+  closedir(d);
 }
 
-#define PIPE_COUNT (4) // number of pipes used to communicate with child proc
+#define PIPE_COUNT 4 // Number of pipes used to communicate with child.
 
-/** Closes all pipes in the given array. */
-static void closePipes(int pipes[], int skipFd) {
-    for (int i = 0; i < PIPE_COUNT * 2; i++) {
-        int fd = pipes[i];
-        if (fd == -1) {
-            return;
-        }
-        if (fd != skipFd) {
-            close(pipes[i]);
-        }
+static void ClosePipes(int pipes[], int skip_fd) {
+  for (int i = 0; i < PIPE_COUNT * 2; i++) {
+    int fd = pipes[i];
+    if (fd != -1 && fd != skip_fd) {
+      close(pipes[i]);
     }
+  }
+}
+
+static void AbortChild(int status_pipe_fd) {
+  int error = errno;
+  TEMP_FAILURE_RETRY(write(status_pipe_fd, &error, sizeof(int)));
+  close(status_pipe_fd);
+  _exit(127);
 }
 
 /** Executes a command in a child process. */
-static pid_t executeProcess(JNIEnv* env, char** commands, char** environment,
-        const char* workingDirectory, jobject inDescriptor,
-        jobject outDescriptor, jobject errDescriptor,
-        jboolean redirectErrorStream) {
+static pid_t ExecuteProcess(JNIEnv* env, char** commands, char** environment,
+                            const char* workingDirectory, jobject inDescriptor,
+                            jobject outDescriptor, jobject errDescriptor,
+                            jboolean redirectErrorStream) {
 
-    // Keep track of the system properties fd so we don't close it.
-    int androidSystemPropertiesFd = -1;
-    char* fdString = getenv("ANDROID_PROPERTY_WORKSPACE");
-    if (fdString) {
-        androidSystemPropertiesFd = atoi(fdString);
+  // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe.
+  int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
+  for (int i = 0; i < PIPE_COUNT; i++) {
+    if (pipe(pipes + i * 2) == -1) {
+      jniThrowIOException(env, errno);
+      ClosePipes(pipes, -1);
+      return -1;
+    }
+  }
+  int stdinIn = pipes[0];
+  int stdinOut = pipes[1];
+  int stdoutIn = pipes[2];
+  int stdoutOut = pipes[3];
+  int stderrIn = pipes[4];
+  int stderrOut = pipes[5];
+  int statusIn = pipes[6];
+  int statusOut = pipes[7];
+
+  pid_t childPid = fork();
+
+  // If fork() failed...
+  if (childPid == -1) {
+    jniThrowIOException(env, errno);
+    ClosePipes(pipes, -1);
+    return -1;
+  }
+
+  // If this is the child process...
+  if (childPid == 0) {
+    // Note: We cannot malloc(3) or free(3) after this point!
+    // A thread in the parent that no longer exists in the child may have held the heap lock
+    // when we forked, so an attempt to malloc(3) or free(3) would result in deadlock.
+
+    // Replace stdin, out, and err with pipes.
+    dup2(stdinIn, 0);
+    dup2(stdoutOut, 1);
+    if (redirectErrorStream) {
+      dup2(stdoutOut, 2);
+    } else {
+      dup2(stderrOut, 2);
     }
 
-    // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe.
-    int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-    for (int i = 0; i < PIPE_COUNT; i++) {
-        if (pipe(pipes + i * 2) == -1) {
-            jniThrowIOException(env, errno);
-            closePipes(pipes, -1);
-            return -1;
-        }
-    }
-    int stdinIn = pipes[0];
-    int stdinOut = pipes[1];
-    int stdoutIn = pipes[2];
-    int stdoutOut = pipes[3];
-    int stderrIn = pipes[4];
-    int stderrOut = pipes[5];
-    int statusIn = pipes[6];
-    int statusOut = pipes[7];
+    // Close all but statusOut. This saves some work in the next step.
+    ClosePipes(pipes, statusOut);
 
-    pid_t childPid = fork();
+    // Make statusOut automatically close if execvp() succeeds.
+    fcntl(statusOut, F_SETFD, FD_CLOEXEC);
 
-    // If fork() failed...
-    if (childPid == -1) {
-        jniThrowIOException(env, errno);
-        closePipes(pipes, -1);
-        return -1;
+    // Close remaining unwanted open fds.
+    CloseNonStandardFds(statusOut);
+
+    // Switch to working directory.
+    if (workingDirectory != NULL) {
+      if (chdir(workingDirectory) == -1) {
+        AbortChild(statusOut);
+      }
     }
 
-    // If this is the child process...
-    if (childPid == 0) {
-        /*
-         * Note: We cannot malloc(3) or free(3) after this point!
-         * A thread in the parent that no longer exists in the child may have held the heap lock
-         * when we forked, so an attempt to malloc(3) or free(3) would result in deadlock.
-         */
-
-        // Replace stdin, out, and err with pipes.
-        dup2(stdinIn, 0);
-        dup2(stdoutOut, 1);
-        if (redirectErrorStream) {
-            dup2(stdoutOut, 2);
-        } else {
-            dup2(stderrOut, 2);
-        }
-
-        // Close all but statusOut. This saves some work in the next step.
-        closePipes(pipes, statusOut);
-
-        // Make statusOut automatically close if execvp() succeeds.
-        fcntl(statusOut, F_SETFD, FD_CLOEXEC);
-
-        // Close remaining unwanted open fds.
-        closeNonStandardFds(statusOut, androidSystemPropertiesFd);
-
-        // Switch to working directory.
-        if (workingDirectory != NULL) {
-            if (chdir(workingDirectory) == -1) {
-                goto execFailed;
-            }
-        }
-
-        // Set up environment.
-        if (environment != NULL) {
-            extern char** environ; // Standard, but not in any header file.
-            environ = environment;
-        }
-
-        // Execute process. By convention, the first argument in the arg array
-        // should be the command itself. In fact, I get segfaults when this
-        // isn't the case.
-        execvp(commands[0], commands);
-
-        // If we got here, execvp() failed or the working dir was invalid.
-execFailed:
-        int error = errno;
-        write(statusOut, &error, sizeof(int));
-        close(statusOut);
-        exit(error);
+    // Set up environment.
+    if (environment != NULL) {
+      extern char** environ; // Standard, but not in any header file.
+      environ = environment;
     }
 
-    // This is the parent process.
+    // Execute process. By convention, the first argument in the arg array
+    // should be the command itself.
+    execvp(commands[0], commands);
+    AbortChild(statusOut);
+  }
 
-    // Close child's pipe ends.
-    close(stdinIn);
-    close(stdoutOut);
-    close(stderrOut);
-    close(statusOut);
+  // This is the parent process.
 
-    // Check status pipe for an error code. If execvp() succeeds, the other
-    // end of the pipe should automatically close, in which case, we'll read
-    // nothing.
-    int result;
-    int count = read(statusIn, &result, sizeof(int));
-    close(statusIn);
-    if (count > 0) {
-        jniThrowIOException(env, result);
+  // Close child's pipe ends.
+  close(stdinIn);
+  close(stdoutOut);
+  close(stderrOut);
+  close(statusOut);
 
-        close(stdoutIn);
-        close(stdinOut);
-        close(stderrIn);
+  // Check status pipe for an error code. If execvp(2) succeeds, the other
+  // end of the pipe should automatically close, in which case, we'll read
+  // nothing.
+  int child_errno;
+  ssize_t count = TEMP_FAILURE_RETRY(read(statusIn, &child_errno, sizeof(int)));
+  close(statusIn);
+  if (count > 0) {
+    // chdir(2) or execvp(2) in the child failed.
+    // TODO: track which so we can be more specific in the detail message.
+    jniThrowIOException(env, child_errno);
 
-        return -1;
+    close(stdoutIn);
+    close(stdinOut);
+    close(stderrIn);
+
+    // Reap our zombie child right away.
+    int status;
+    int rc = TEMP_FAILURE_RETRY(waitpid(childPid, &status, 0));
+    if (rc == -1) {
+      ALOGW("waitpid on failed exec failed: %s", strerror(errno));
     }
 
-    // Fill in file descriptor wrappers.
-    jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn);
-    jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut);
-    jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn);
+    return -1;
+  }
 
-    return childPid;
+  // Fill in file descriptor wrappers.
+  jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn);
+  jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut);
+  jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn);
+
+  return childPid;
 }
 
 /**
- * Converts Java String[] to char** and delegates to executeProcess().
+ * Converts Java String[] to char** and delegates to ExecuteProcess().
  */
 static pid_t ProcessManager_exec(JNIEnv* env, jclass, jobjectArray javaCommands,
-        jobjectArray javaEnvironment, jstring javaWorkingDirectory,
-        jobject inDescriptor, jobject outDescriptor, jobject errDescriptor,
-        jboolean redirectErrorStream) {
+                                 jobjectArray javaEnvironment, jstring javaWorkingDirectory,
+                                 jobject inDescriptor, jobject outDescriptor, jobject errDescriptor,
+                                 jboolean redirectErrorStream) {
 
-    // Copy commands into char*[].
-    char** commands = convertStrings(env, javaCommands);
+  ExecStrings commands(env, javaCommands);
+  ExecStrings environment(env, javaEnvironment);
 
-    // Extract working directory string.
-    const char* workingDirectory = NULL;
-    if (javaWorkingDirectory != NULL) {
-        workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL);
-    }
+  // Extract working directory string.
+  const char* workingDirectory = NULL;
+  if (javaWorkingDirectory != NULL) {
+    workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL);
+  }
 
-    // Convert environment array.
-    char** environment = convertStrings(env, javaEnvironment);
+  pid_t result = ExecuteProcess(env, commands.get(), environment.get(), workingDirectory,
+                                inDescriptor, outDescriptor, errDescriptor, redirectErrorStream);
 
-    pid_t result = executeProcess(env, commands, environment, workingDirectory,
-            inDescriptor, outDescriptor, errDescriptor, redirectErrorStream);
+  // Clean up working directory string.
+  if (javaWorkingDirectory != NULL) {
+    env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory);
+  }
 
-    // Temporarily clear exception so we can clean up.
-    jthrowable exception = env->ExceptionOccurred();
-    env->ExceptionClear();
-
-    freeStrings(env, javaEnvironment, environment);
-
-    // Clean up working directory string.
-    if (javaWorkingDirectory != NULL) {
-        env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory);
-    }
-
-    freeStrings(env, javaCommands, commands);
-
-    // Re-throw exception if present.
-    if (exception != NULL) {
-        if (env->Throw(exception) < 0) {
-            ALOGE("Error rethrowing exception!");
-        }
-    }
-
-    return result;
+  return result;
 }
 
-static JNINativeMethod methods[] = {
-    NATIVE_METHOD(ProcessManager, exec, "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Z)I"),
+static JNINativeMethod gMethods[] = {
+  NATIVE_METHOD(ProcessManager, exec, "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Z)I"),
 };
 void register_java_lang_ProcessManager(JNIEnv* env) {
-    jniRegisterNativeMethods(env, "java/lang/ProcessManager", methods, NELEM(methods));
+  jniRegisterNativeMethods(env, "java/lang/ProcessManager", gMethods, NELEM(gMethods));
 }
diff --git a/luni/src/main/native/java_lang_System.cpp b/luni/src/main/native/java_lang_System.cpp
index 8cfd070..0686310 100644
--- a/luni/src/main/native/java_lang_System.cpp
+++ b/luni/src/main/native/java_lang_System.cpp
@@ -30,6 +30,8 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/time.h>
+#include <time.h>
 #include <unistd.h>
 
 static void System_log(JNIEnv* env, jclass, jchar type, jstring javaMessage, jthrowable exception) {
@@ -83,8 +85,36 @@
     return toStringArray(env, properties);
 }
 
+static jlong System_currentTimeMillis(JNIEnv*, jclass) {
+    timeval now;
+    gettimeofday(&now, NULL);
+    jlong when = now.tv_sec * 1000LL + now.tv_usec / 1000;
+    return when;
+}
+
+static jlong System_nanoTime(JNIEnv*, jclass) {
+    timespec now;
+    clock_gettime(CLOCK_MONOTONIC, &now);
+    return now.tv_sec * 1000000000LL + now.tv_nsec;
+}
+
+static jstring System_mapLibraryName(JNIEnv* env, jclass, jstring javaName) {
+    ScopedUtfChars name(env, javaName);
+    if (name.c_str() == NULL) {
+        return NULL;
+    }
+    char* mappedName = NULL;
+    asprintf(&mappedName, OS_SHARED_LIB_FORMAT_STR, name.c_str());
+    jstring result = env->NewStringUTF(mappedName);
+    free(mappedName);
+    return result;
+}
+
 static JNINativeMethod gMethods[] = {
+    NATIVE_METHOD(System, currentTimeMillis, "()J"),
     NATIVE_METHOD(System, log, "(CLjava/lang/String;Ljava/lang/Throwable;)V"),
+    NATIVE_METHOD(System, mapLibraryName, "(Ljava/lang/String;)Ljava/lang/String;"),
+    NATIVE_METHOD(System, nanoTime, "()J"),
     NATIVE_METHOD(System, setFieldImpl, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V"),
     NATIVE_METHOD(System, specialProperties, "()[Ljava/lang/String;"),
 };
diff --git a/luni/src/main/native/java_math_NativeBN.cpp b/luni/src/main/native/java_math_NativeBN.cpp
index 5e111d7..158dfac 100644
--- a/luni/src/main/native/java_math_NativeBN.cpp
+++ b/luni/src/main/native/java_math_NativeBN.cpp
@@ -14,14 +14,11 @@
  * limitations under the License.
  */
 
-/*
- * Native glue for Java class org.openssl.NativeBN
- */
-
 #define LOG_TAG "NativeBN"
 
 #include "JNIHelp.h"
 #include "JniConstants.h"
+#include "JniException.h"
 #include "ScopedPrimitiveArray.h"
 #include "ScopedUtfChars.h"
 #include "StaticAssert.h"
@@ -33,260 +30,286 @@
 #include <stdio.h>
 
 struct BN_CTX_Deleter {
-    void operator()(BN_CTX* p) const {
-        BN_CTX_free(p);
-    }
+  void operator()(BN_CTX* p) const {
+    BN_CTX_free(p);
+  }
 };
 typedef UniquePtr<BN_CTX, BN_CTX_Deleter> Unique_BN_CTX;
 
-static int isValidHandle (JNIEnv* env, void* handle, const char* message) {
-    if (handle == NULL) {
-        jniThrowNullPointerException(env, message);
-        return JNI_FALSE;
-    }
-    return JNI_TRUE;
+static BIGNUM* toBigNum(jlong address) {
+  return reinterpret_cast<BIGNUM*>(static_cast<uintptr_t>(address));
 }
 
-static int oneValidHandle (JNIEnv* env, void* a)
-{
-    return isValidHandle(env, a, "Mandatory handle (first) passed as null");
+static bool throwExceptionIfNecessary(JNIEnv* env) {
+  long error = ERR_get_error();
+  if (error == 0) {
+    return false;
+  }
+  char message[256];
+  ERR_error_string_n(error, message, sizeof(message));
+  int reason = ERR_GET_REASON(error);
+  if (reason == BN_R_DIV_BY_ZERO) {
+    jniThrowException(env, "java/lang/ArithmeticException", "BigInteger division by zero");
+  } else if (reason == BN_R_NO_INVERSE) {
+    jniThrowException(env, "java/lang/ArithmeticException", "BigInteger not invertible");
+  } else if (reason == ERR_R_MALLOC_FAILURE) {
+    jniThrowOutOfMemoryError(env, message);
+  } else {
+    jniThrowException(env, "java/lang/ArithmeticException", message);
+  }
+  return true;
 }
 
-static int twoValidHandles (JNIEnv* env, void* a, void* b)
-{
-    if (!oneValidHandle(env, a)) return JNI_FALSE;
-    return isValidHandle(env, b, "Mandatory handle (second) passed as null");
+static int isValidHandle(JNIEnv* env, jlong handle, const char* message) {
+  if (handle == 0) {
+    jniThrowNullPointerException(env, message);
+    return JNI_FALSE;
+  }
+  return JNI_TRUE;
 }
 
-static int threeValidHandles (JNIEnv* env, void* a, void* b, void* c)
-{
-    if (!twoValidHandles(env, a, b)) return JNI_FALSE;
-    return isValidHandle(env, c, "Mandatory handle (third) passed as null");
+static int oneValidHandle(JNIEnv* env, jlong a) {
+  return isValidHandle(env, a, "Mandatory handle (first) passed as null");
 }
 
-static int fourValidHandles (JNIEnv* env, void* a, void* b, void* c, void* d)
-{
-    if (!threeValidHandles(env, a, b, c)) return JNI_FALSE;
-    return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
+static int twoValidHandles(JNIEnv* env, jlong a, jlong b) {
+  if (!oneValidHandle(env, a)) return JNI_FALSE;
+  return isValidHandle(env, b, "Mandatory handle (second) passed as null");
 }
 
-static unsigned long NativeBN_ERR_get_error(JNIEnv*, jclass) {
-    return ERR_get_error();
+static int threeValidHandles(JNIEnv* env, jlong a, jlong b, jlong c) {
+  if (!twoValidHandles(env, a, b)) return JNI_FALSE;
+  return isValidHandle(env, c, "Mandatory handle (third) passed as null");
 }
 
-static jstring NativeBN_ERR_error_string(JNIEnv* env, jclass, unsigned long e) {
-    char* errStr = ERR_error_string(e, NULL);
-    return env->NewStringUTF(errStr);
+static int fourValidHandles(JNIEnv* env, jlong a, jlong b, jlong c, jlong d) {
+  if (!threeValidHandles(env, a, b, c)) return JNI_FALSE;
+  return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
 }
 
-static BIGNUM* NativeBN_BN_new(JNIEnv*, jclass) {
-    return BN_new();
+static jlong NativeBN_BN_new(JNIEnv* env, jclass) {
+  jlong result = static_cast<jlong>(reinterpret_cast<uintptr_t>(BN_new()));
+  throwExceptionIfNecessary(env);
+  return result;
 }
 
-static void NativeBN_BN_free(JNIEnv* env, jclass, BIGNUM* a) {
-    if (!oneValidHandle(env, a)) return;
-    BN_free(a);
+static void NativeBN_BN_free(JNIEnv* env, jclass, jlong a) {
+  if (!oneValidHandle(env, a)) return;
+  BN_free(toBigNum(a));
 }
 
-static int NativeBN_BN_cmp(JNIEnv* env, jclass, BIGNUM* a, BIGNUM* b) {
-    if (!twoValidHandles(env, a, b)) return 1;
-    return BN_cmp(a, b);
+static int NativeBN_BN_cmp(JNIEnv* env, jclass, jlong a, jlong b) {
+  if (!twoValidHandles(env, a, b)) return 1;
+  return BN_cmp(toBigNum(a), toBigNum(b));
 }
 
-static jboolean NativeBN_BN_copy(JNIEnv* env, jclass, BIGNUM* to, BIGNUM* from) {
-    if (!twoValidHandles(env, to, from)) return JNI_FALSE;
-    return (BN_copy(to, from) != NULL);
+static void NativeBN_BN_copy(JNIEnv* env, jclass, jlong to, jlong from) {
+  if (!twoValidHandles(env, to, from)) return;
+  BN_copy(toBigNum(to), toBigNum(from));
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_putULongInt(JNIEnv* env, jclass, BIGNUM* a, unsigned long long dw, jboolean neg) {
-    if (!oneValidHandle(env, a)) return JNI_FALSE;
+static void NativeBN_putULongInt(JNIEnv* env, jclass, jlong a0, unsigned long long dw, jboolean neg) {
+    if (!oneValidHandle(env, a0)) return;
     unsigned int hi = dw >> 32; // This shifts without sign extension.
-    int lo = (int)dw; // This truncates implicitely.
+    int lo = (int)dw; // This truncates implicitly.
 
     // cf. litEndInts2bn:
+    BIGNUM* a = toBigNum(a0);
     bn_check_top(a);
-        if (bn_wexpand(a, 2) != NULL) {
-            a->d[0] = lo;
-            a->d[1] = hi;
-            a->top = 2;
-            a->neg = neg;
-            bn_correct_top(a);
-            return JNI_TRUE;
-        }
-        else return JNI_FALSE;
+    if (bn_wexpand(a, 2) != NULL) {
+      a->d[0] = lo;
+      a->d[1] = hi;
+      a->top = 2;
+      a->neg = neg;
+      bn_correct_top(a);
+    } else {
+      throwExceptionIfNecessary(env);
+    }
 }
 
-static jboolean NativeBN_putLongInt(JNIEnv* env, jclass cls, BIGNUM* a, long long dw) {
-    if (dw >= 0) return NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE);
-    else return NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE);
+static void NativeBN_putLongInt(JNIEnv* env, jclass cls, jlong a, long long dw) {
+  if (dw >= 0) {
+    NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE);
+  } else {
+    NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE);
+  }
 }
 
-static int NativeBN_BN_dec2bn(JNIEnv* env, jclass, BIGNUM* a, jstring str) {
-    if (!oneValidHandle(env, a)) return -1;
-    ScopedUtfChars chars(env, str);
-    if (chars.c_str() == NULL) {
-        return -1;
-    }
-    return BN_dec2bn(&a, chars.c_str());
+static int NativeBN_BN_dec2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
+  if (!oneValidHandle(env, a0)) return -1;
+  ScopedUtfChars chars(env, str);
+  if (chars.c_str() == NULL) {
+    return -1;
+  }
+  BIGNUM* a = toBigNum(a0);
+  int result = BN_dec2bn(&a, chars.c_str());
+  throwExceptionIfNecessary(env);
+  return result;
 }
 
-static int NativeBN_BN_hex2bn(JNIEnv* env, jclass, BIGNUM* a, jstring str) {
-    if (!oneValidHandle(env, a)) return -1;
-    ScopedUtfChars chars(env, str);
-    if (chars.c_str() == NULL) {
-        return -1;
-    }
-    return BN_hex2bn(&a, chars.c_str());
+static int NativeBN_BN_hex2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
+  if (!oneValidHandle(env, a0)) return -1;
+  ScopedUtfChars chars(env, str);
+  if (chars.c_str() == NULL) {
+    return -1;
+  }
+  BIGNUM* a = toBigNum(a0);
+  int result = BN_hex2bn(&a, chars.c_str());
+  throwExceptionIfNecessary(env);
+  return result;
 }
 
-static jboolean NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, BIGNUM* ret) {
-    if (!oneValidHandle(env, ret)) return JNI_FALSE;
-    ScopedByteArrayRO bytes(env, arr);
-    if (bytes.get() == NULL) {
-        return -1;
-    }
-    jboolean success = (BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, ret) != NULL);
-    if (success && neg) {
-        BN_set_negative(ret, 1);
-    }
-    return success;
+static void NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, jlong ret) {
+  if (!oneValidHandle(env, ret)) return;
+  ScopedByteArrayRO bytes(env, arr);
+  if (bytes.get() == NULL) {
+    return;
+  }
+  BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, toBigNum(ret));
+  if (!throwExceptionIfNecessary(env) && neg) {
+    BN_set_negative(toBigNum(ret), true);
+  }
 }
 
 /**
- * public static native boolean litEndInts2bn(int[], int, int, int)
  * Note:
  * This procedure directly writes the internal representation of BIGNUMs.
  * We do so as there is no direct interface based on Little Endian Integer Arrays.
  * Also note that the same representation is used in the Cordoba Java Implementation of BigIntegers,
  *        whereof certain functionality is still being used.
  */
-static jboolean NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, BIGNUM* ret) {
-    if (!oneValidHandle(env, ret)) return JNI_FALSE;
-    bn_check_top(ret);
-    if (len > 0) {
-        ScopedIntArrayRO scopedArray(env, arr);
-        if (scopedArray.get() == NULL) {
-            return JNI_FALSE;
-        }
-
-        STATIC_ASSERT(sizeof(BN_ULONG) == sizeof(jint), BN_ULONG_not_32_bit);
-        const BN_ULONG* tmpInts = reinterpret_cast<const BN_ULONG*>(scopedArray.get());
-        if ((tmpInts != NULL) && (bn_wexpand(ret, len) != NULL)) {
-            int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
-            ret->top = len;
-            ret->neg = neg;
-            // need to call this due to clear byte at top if avoiding
-            // having the top bit set (-ve number)
-            // Basically get rid of top zero ints:
-            bn_correct_top(ret);
-            return JNI_TRUE;
-        } else {
-            return JNI_FALSE;
-        }
-    } else { // (len = 0) means value = 0 and sign will be 0, too.
-        ret->top = 0;
-        return JNI_TRUE;
+static void NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, jlong ret0) {
+  if (!oneValidHandle(env, ret0)) return;
+  BIGNUM* ret = toBigNum(ret0);
+  bn_check_top(ret);
+  if (len > 0) {
+    ScopedIntArrayRO scopedArray(env, arr);
+    if (scopedArray.get() == NULL) {
+      return;
     }
+
+    STATIC_ASSERT(sizeof(BN_ULONG) == sizeof(jint), BN_ULONG_not_32_bit);
+    const BN_ULONG* tmpInts = reinterpret_cast<const BN_ULONG*>(scopedArray.get());
+    if ((tmpInts != NULL) && (bn_wexpand(ret, len) != NULL)) {
+      int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
+      ret->top = len;
+      ret->neg = neg;
+      // need to call this due to clear byte at top if avoiding
+      // having the top bit set (-ve number)
+      // Basically get rid of top zero ints:
+      bn_correct_top(ret);
+    } else {
+      throwExceptionIfNecessary(env);
+    }
+  } else { // (len = 0) means value = 0 and sign will be 0, too.
+    ret->top = 0;
+  }
 }
 
 
 #define BYTES2INT(bytes, k) \
- (  (bytes[k + 3] & 0xFF) \
-  | (bytes[k + 2] & 0xFF) << 8 \
-  | (bytes[k + 1] & 0xFF) << 16 \
-  | (bytes[k + 0] & 0xFF) << 24 )
+    ((bytes[k + 3] & 0xff) | (bytes[k + 2] & 0xff) << 8 | (bytes[k + 1] & 0xff) << 16 | (bytes[k + 0] & 0xff) << 24)
 
-static jboolean negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, BIGNUM* ret) {
-    // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
-    bn_check_top(ret);
-    // FIXME: assert bytesLen > 0
-    int intLen = (bytesLen + 3) / 4;
-    int firstNonzeroDigit = -2;
-    if (bn_wexpand(ret, intLen) != NULL) {
-        BN_ULONG* d = ret->d;
-        BN_ULONG di;
-        ret->top = intLen;
-        int highBytes = bytesLen % 4;
-        int k = bytesLen;
-        // Put bytes to the int array starting from the end of the byte array
-        int i = 0;
+static void negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, jlong ret0) {
+  BIGNUM* ret = toBigNum(ret0);
+
+  // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
+  bn_check_top(ret);
+  // FIXME: assert bytesLen > 0
+  int intLen = (bytesLen + 3) / 4;
+  int firstNonzeroDigit = -2;
+  if (bn_wexpand(ret, intLen) != NULL) {
+    BN_ULONG* d = ret->d;
+    BN_ULONG di;
+    ret->top = intLen;
+    int highBytes = bytesLen % 4;
+    int k = bytesLen;
+    // Put bytes to the int array starting from the end of the byte array
+    int i = 0;
+    while (k > highBytes) {
+      k -= 4;
+      di = BYTES2INT(bytes, k);
+      if (di != 0) {
+        d[i] = -di;
+        firstNonzeroDigit = i;
+        i++;
         while (k > highBytes) {
-            k -= 4;
-            di = BYTES2INT(bytes, k);
-            if (di != 0) {
-                d[i] = -di;
-                firstNonzeroDigit = i;
-                i++;
-                while (k > highBytes) {
-                    k -= 4;
-                    d[i] = ~BYTES2INT(bytes, k);
-                    i++;
-                }
-                break;
-            } else {
-                d[i] = 0;
-                i++;
-            }
+          k -= 4;
+          d[i] = ~BYTES2INT(bytes, k);
+          i++;
         }
-        if (highBytes != 0) {
-            di = -1;
-            // Put the first bytes in the highest element of the int array
-            if (firstNonzeroDigit != -2) {
-                for (k = 0; k < highBytes; k++) {
-                    di = (di << 8) | (bytes[k] & 0xFF);
-                }
-                d[i] = ~di;
-            } else {
-                for (k = 0; k < highBytes; k++) {
-                    di = (di << 8) | (bytes[k] & 0xFF);
-                }
-                d[i] = -di;
-            }
-        }
-        return JNI_TRUE;
+        break;
+      } else {
+        d[i] = 0;
+        i++;
+      }
     }
-    else return JNI_FALSE;
+    if (highBytes != 0) {
+      di = -1;
+      // Put the first bytes in the highest element of the int array
+      if (firstNonzeroDigit != -2) {
+        for (k = 0; k < highBytes; k++) {
+          di = (di << 8) | (bytes[k] & 0xFF);
+        }
+        d[i] = ~di;
+      } else {
+        for (k = 0; k < highBytes; k++) {
+          di = (di << 8) | (bytes[k] & 0xFF);
+        }
+        d[i] = -di;
+      }
+    }
+  }
 }
 
-static jboolean NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, BIGNUM* ret) {
-    if (!oneValidHandle(env, ret)) return JNI_FALSE;
-    ScopedByteArrayRO bytes(env, arr);
-    if (bytes.get() == NULL) {
-        return -1;
-    }
-    jboolean success;
-    const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
-    if ((bytes[0] & 0X80) == 0) { // Positive value!
-        //
-        // We can use the existing BN implementation for unsigned big endian bytes:
-        //
-        success = (BN_bin2bn(s, bytesLen, ret) != NULL);
-        BN_set_negative(ret, JNI_FALSE);
-    } else { // Negative value!
-        //
-        // We need to apply two's complement:
-        //
-        success = negBigEndianBytes2bn(env, cls, s, bytesLen, ret);
-        BN_set_negative(ret, JNI_TRUE);
-    }
-    return success;
+static void NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, jlong ret0) {
+  if (!oneValidHandle(env, ret0)) return;
+  BIGNUM* ret = toBigNum(ret0);
+
+  ScopedByteArrayRO bytes(env, arr);
+  if (bytes.get() == NULL) {
+    return;
+  }
+  const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
+  if ((bytes[0] & 0X80) == 0) { // Positive value!
+    //
+    // We can use the existing BN implementation for unsigned big endian bytes:
+    //
+    BN_bin2bn(s, bytesLen, ret);
+    BN_set_negative(ret, false);
+  } else { // Negative value!
+    //
+    // We need to apply two's complement:
+    //
+    negBigEndianBytes2bn(env, cls, s, bytesLen, ret0);
+    BN_set_negative(ret, true);
+  }
+  throwExceptionIfNecessary(env);
 }
 
-static long long NativeBN_longInt(JNIEnv* env, jclass, BIGNUM* a) {
-    if (!oneValidHandle(env, a)) return -1;
-    bn_check_top(a);
-    int intLen = a->top;
-    BN_ULONG* d = a->d;
-    switch (intLen) {
+static long long NativeBN_longInt(JNIEnv* env, jclass, jlong a0) {
+  if (!oneValidHandle(env, a0)) return -1;
+  BIGNUM* a = toBigNum(a0);
+  bn_check_top(a);
+  int intLen = a->top;
+  BN_ULONG* d = a->d;
+  switch (intLen) {
     case 0:
-        return 0;
+      return 0;
     case 1:
-        if (!a->neg) return d[0] & 0X00000000FFFFFFFFLL;
-        else return -(d[0] & 0X00000000FFFFFFFFLL);
+      if (!a->neg) {
+        return d[0] & 0X00000000FFFFFFFFLL;
+      } else {
+        return -(d[0] & 0X00000000FFFFFFFFLL);
+      }
     default:
-        if (!a->neg) return ((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL);
-        else return -(((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL));
-    }
+      if (!a->neg) {
+        return ((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL);
+      } else {
+        return -(((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL));
+      }
+  }
 }
 
 static char* leadingZerosTrimmed(char* s) {
@@ -302,256 +325,250 @@
     return p;
 }
 
-static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, BIGNUM* a) {
-    if (!oneValidHandle(env, a)) return NULL;
-    char* tmpStr;
-    char* retStr;
-    tmpStr = BN_bn2dec(a);
-    if (tmpStr != NULL) {
-        retStr = leadingZerosTrimmed(tmpStr);
-        jstring returnJString = env->NewStringUTF(retStr);
-        OPENSSL_free(tmpStr);
-        return returnJString;
-    }
-    else return NULL;
+static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, jlong a) {
+  if (!oneValidHandle(env, a)) return NULL;
+  char* tmpStr = BN_bn2dec(toBigNum(a));
+  if (tmpStr == NULL) {
+    return NULL;
+  }
+  char* retStr = leadingZerosTrimmed(tmpStr);
+  jstring returnJString = env->NewStringUTF(retStr);
+  OPENSSL_free(tmpStr);
+  return returnJString;
 }
 
-static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, BIGNUM* a) {
-    if (!oneValidHandle(env, a)) return NULL;
-    char* tmpStr;
-    char* retStr;
-    tmpStr = BN_bn2hex(a);
-    if (tmpStr != NULL) {
-        retStr = leadingZerosTrimmed(tmpStr);
-        jstring returnJString = env->NewStringUTF(retStr);
-        OPENSSL_free(tmpStr);
-        return returnJString;
-    }
-    else return NULL;
+static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, jlong a) {
+  if (!oneValidHandle(env, a)) return NULL;
+  char* tmpStr = BN_bn2hex(toBigNum(a));
+  if (tmpStr == NULL) {
+    return NULL;
+  }
+  char* retStr = leadingZerosTrimmed(tmpStr);
+  jstring returnJString = env->NewStringUTF(retStr);
+  OPENSSL_free(tmpStr);
+  return returnJString;
 }
 
-static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, BIGNUM* a) {
-    if (!oneValidHandle(env, a)) return NULL;
-    jbyteArray result = env->NewByteArray(BN_num_bytes(a));
-    if (result == NULL) {
-        return NULL;
-    }
-    ScopedByteArrayRW bytes(env, result);
-    if (bytes.get() == NULL) {
-        return NULL;
-    }
-    BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
-    return result;
+static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, jlong a0) {
+  if (!oneValidHandle(env, a0)) return NULL;
+  BIGNUM* a = toBigNum(a0);
+  jbyteArray result = env->NewByteArray(BN_num_bytes(a));
+  if (result == NULL) {
+    return NULL;
+  }
+  ScopedByteArrayRW bytes(env, result);
+  if (bytes.get() == NULL) {
+    return NULL;
+  }
+  BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
+  return result;
 }
 
-static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, BIGNUM* a) {
-    if (!oneValidHandle(env, a)) return NULL;
-    bn_check_top(a);
-    int len = a->top;
-    if (len == 0) {
-        return NULL;
-    }
-    jintArray result = env->NewIntArray(len);
-    if (result == NULL) {
-        return NULL;
-    }
-    ScopedIntArrayRW ints(env, result);
-    if (ints.get() == NULL) {
-        return NULL;
-    }
-    BN_ULONG* ulongs = reinterpret_cast<BN_ULONG*>(ints.get());
-    if (ulongs == NULL) {
-        return NULL;
-    }
-    int i = len; do { i--; ulongs[i] = a->d[i]; } while (i > 0);
-    return result;
+static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, jlong a0) {
+  if (!oneValidHandle(env, a0)) return NULL;
+  BIGNUM* a = toBigNum(a0);
+  bn_check_top(a);
+  int len = a->top;
+  if (len == 0) {
+    return NULL;
+  }
+  jintArray result = env->NewIntArray(len);
+  if (result == NULL) {
+    return NULL;
+  }
+  ScopedIntArrayRW ints(env, result);
+  if (ints.get() == NULL) {
+    return NULL;
+  }
+  BN_ULONG* ulongs = reinterpret_cast<BN_ULONG*>(ints.get());
+  if (ulongs == NULL) {
+    return NULL;
+  }
+  int i = len; do { i--; ulongs[i] = a->d[i]; } while (i > 0);
+  return result;
 }
 
-static int NativeBN_sign(JNIEnv* env, jclass, BIGNUM* a) {
-    if (!oneValidHandle(env, a)) return -2;
-    if (BN_is_zero(a)) return 0;
-    else if (BN_is_negative(a)) return -1;
-    else return 1;
+static int NativeBN_sign(JNIEnv* env, jclass, jlong a) {
+  if (!oneValidHandle(env, a)) return -2;
+  if (BN_is_zero(toBigNum(a))) {
+      return 0;
+  } else if (BN_is_negative(toBigNum(a))) {
+    return -1;
+  }
+  return 1;
 }
 
-static void NativeBN_BN_set_negative(JNIEnv* env, jclass, BIGNUM* b, int n) {
-    if (!oneValidHandle(env, b)) return;
-    BN_set_negative(b, n);
+static void NativeBN_BN_set_negative(JNIEnv* env, jclass, jlong b, int n) {
+  if (!oneValidHandle(env, b)) return;
+  BN_set_negative(toBigNum(b), n);
 }
 
-static int NativeBN_bitLength(JNIEnv* env, jclass, BIGNUM* a) {
+static int NativeBN_bitLength(JNIEnv* env, jclass, jlong a0) {
 // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
 //
-    if (!oneValidHandle(env, a)) return JNI_FALSE;
-    bn_check_top(a);
-    int intLen = a->top;
-    if (intLen == 0) return 0;
-    BN_ULONG* d = a->d;
-    int i = intLen - 1;
-    BN_ULONG msd = d[i]; // most significant digit
-        if (a->neg) {
-            // Handle negative values correctly:
-            // i.e. decrement the msd if all other digits are 0:
-            // while ((i > 0) && (d[i] != 0)) { i--; }
-            do { i--; } while (!((i < 0) || (d[i] != 0)));
-            if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
-        }
-        return (intLen - 1) * 32 + BN_num_bits_word(msd);
+  if (!oneValidHandle(env, a0)) return JNI_FALSE;
+  BIGNUM* a = toBigNum(a0);
+  bn_check_top(a);
+  int intLen = a->top;
+  if (intLen == 0) return 0;
+  BN_ULONG* d = a->d;
+  int i = intLen - 1;
+  BN_ULONG msd = d[i]; // most significant digit
+  if (a->neg) {
+    // Handle negative values correctly:
+    // i.e. decrement the msd if all other digits are 0:
+    // while ((i > 0) && (d[i] != 0)) { i--; }
+    do { i--; } while (!((i < 0) || (d[i] != 0)));
+    if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
+  }
+  return (intLen - 1) * 32 + BN_num_bits_word(msd);
 }
 
-static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, BIGNUM* a, int n) {
-    if (!oneValidHandle(env, a)) return JNI_FALSE;
-    return (jboolean)BN_is_bit_set(a, n);
+static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, jlong a, int n) {
+  if (!oneValidHandle(env, a)) return JNI_FALSE;
+  return BN_is_bit_set(toBigNum(a), n);
 }
 
-static jboolean NativeBN_modifyBit(JNIEnv* env, jclass, BIGNUM* a, int n, int op) {
-// ALOGD("NativeBN_BN_modifyBit");
-    if (!oneValidHandle(env, a)) return JNI_FALSE;
-    switch (op) {
-    case 1: return BN_set_bit(a, n);
-    case 0: return BN_clear_bit(a, n);
-    case -1:
-        if (BN_is_bit_set(a, n)) return BN_clear_bit(a, n);
-        else return BN_set_bit(a, n);
-    }
-    return JNI_FALSE;
+static void NativeBN_BN_shift(JNIEnv* env, jclass, jlong r, jlong a, int n) {
+  if (!twoValidHandles(env, r, a)) return;
+  if (n >= 0) {
+    BN_lshift(toBigNum(r), toBigNum(a), n);
+  } else {
+    BN_rshift(toBigNum(r), toBigNum(a), -n);
+  }
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_shift(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, int n) {
-    if (!twoValidHandles(env, r, a)) return JNI_FALSE;
-    return (n >= 0) ? BN_lshift(r, a, n) : BN_rshift(r, a, -n);
+static void NativeBN_BN_add_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
+  if (!oneValidHandle(env, a)) return;
+  BN_add_word(toBigNum(a), w);
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_add_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
-    if (!oneValidHandle(env, a)) return JNI_FALSE;
-    return BN_add_word(a, w);
+static void NativeBN_BN_mul_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
+  if (!oneValidHandle(env, a)) return;
+  BN_mul_word(toBigNum(a), w);
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_sub_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
-    if (!oneValidHandle(env, a)) return JNI_FALSE;
-    return BN_sub_word(a, w);
+static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
+  if (!oneValidHandle(env, a)) return 0;
+  int result = BN_mod_word(toBigNum(a), w);
+  throwExceptionIfNecessary(env);
+  return result;
 }
 
-static jboolean NativeBN_BN_mul_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
-    if (!oneValidHandle(env, a)) return JNI_FALSE;
-    return BN_mul_word(a, w);
+static void NativeBN_BN_add(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
+  if (!threeValidHandles(env, r, a, b)) return;
+  BN_add(toBigNum(r), toBigNum(a), toBigNum(b));
+  throwExceptionIfNecessary(env);
 }
 
-static BN_ULONG NativeBN_BN_div_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
-    if (!oneValidHandle(env, a)) return JNI_FALSE;
-    return BN_div_word(a, w);
+static void NativeBN_BN_sub(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
+  if (!threeValidHandles(env, r, a, b)) return;
+  BN_sub(toBigNum(r), toBigNum(a), toBigNum(b));
+  throwExceptionIfNecessary(env);
 }
 
-static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
-    if (!oneValidHandle(env, a)) return JNI_FALSE;
-    return BN_mod_word(a, w);
+static void NativeBN_BN_gcd(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
+  if (!threeValidHandles(env, r, a, b)) return;
+  Unique_BN_CTX ctx(BN_CTX_new());
+  BN_gcd(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_add(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
-    if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
-    return BN_add(r, a, b);
+static void NativeBN_BN_mul(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
+  if (!threeValidHandles(env, r, a, b)) return;
+  Unique_BN_CTX ctx(BN_CTX_new());
+  BN_mul(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_sub(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
-    if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
-    return BN_sub(r, a, b);
+static void NativeBN_BN_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p) {
+  if (!threeValidHandles(env, r, a, p)) return;
+  Unique_BN_CTX ctx(BN_CTX_new());
+  BN_exp(toBigNum(r), toBigNum(a), toBigNum(p), ctx.get());
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_gcd(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
-    if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
-    Unique_BN_CTX ctx(BN_CTX_new());
-    return BN_gcd(r, a, b, ctx.get());
+static void NativeBN_BN_div(JNIEnv* env, jclass, jlong dv, jlong rem, jlong m, jlong d) {
+  if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return;
+  Unique_BN_CTX ctx(BN_CTX_new());
+  BN_div(toBigNum(dv), toBigNum(rem), toBigNum(m), toBigNum(d), ctx.get());
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_mul(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
-    if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
-    Unique_BN_CTX ctx(BN_CTX_new());
-    return BN_mul(r, a, b, ctx.get());
+static void NativeBN_BN_nnmod(JNIEnv* env, jclass, jlong r, jlong a, jlong m) {
+  if (!threeValidHandles(env, r, a, m)) return;
+  Unique_BN_CTX ctx(BN_CTX_new());
+  BN_nnmod(toBigNum(r), toBigNum(a), toBigNum(m), ctx.get());
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p) {
-    if (!threeValidHandles(env, r, a, p)) return JNI_FALSE;
-    Unique_BN_CTX ctx(BN_CTX_new());
-    return BN_exp(r, a, p, ctx.get());
+static void NativeBN_BN_mod_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p, jlong m) {
+  if (!fourValidHandles(env, r, a, p, m)) return;
+  Unique_BN_CTX ctx(BN_CTX_new());
+  BN_mod_exp(toBigNum(r), toBigNum(a), toBigNum(p), toBigNum(m), ctx.get());
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_div(JNIEnv* env, jclass, BIGNUM* dv, BIGNUM* rem, BIGNUM* m, BIGNUM* d) {
-    if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return JNI_FALSE;
-    Unique_BN_CTX ctx(BN_CTX_new());
-    return BN_div(dv, rem, m, d, ctx.get());
+static void NativeBN_BN_mod_inverse(JNIEnv* env, jclass, jlong ret, jlong a, jlong n) {
+  if (!threeValidHandles(env, ret, a, n)) return;
+  Unique_BN_CTX ctx(BN_CTX_new());
+  BN_mod_inverse(toBigNum(ret), toBigNum(a), toBigNum(n), ctx.get());
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_nnmod(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* m) {
-    if (!threeValidHandles(env, r, a, m)) return JNI_FALSE;
-    Unique_BN_CTX ctx(BN_CTX_new());
-    return BN_nnmod(r, a, m, ctx.get());
+static void NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, jlong ret, int bits,
+                                          jboolean safe, jlong add, jlong rem, jlong cb) {
+  if (!oneValidHandle(env, ret)) return;
+  BN_generate_prime_ex(toBigNum(ret), bits, safe, toBigNum(add), toBigNum(rem),
+                       reinterpret_cast<BN_GENCB*>(cb));
+  throwExceptionIfNecessary(env);
 }
 
-static jboolean NativeBN_BN_mod_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p, BIGNUM* m) {
-    if (!fourValidHandles(env, r, a, p, m)) return JNI_FALSE;
-    Unique_BN_CTX ctx(BN_CTX_new());
-    return BN_mod_exp(r, a, p, m, ctx.get());
-}
-
-static jboolean NativeBN_BN_mod_inverse(JNIEnv* env, jclass, BIGNUM* ret, BIGNUM* a, BIGNUM* n) {
-    if (!threeValidHandles(env, ret, a, n)) return JNI_FALSE;
-    Unique_BN_CTX ctx(BN_CTX_new());
-    return (BN_mod_inverse(ret, a, n, ctx.get()) != NULL);
-}
-
-static jboolean NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, BIGNUM* ret, int bits, jboolean safe,
-        BIGNUM* add, BIGNUM* rem, jint cb) {
-    if (!oneValidHandle(env, ret)) return JNI_FALSE;
-    return BN_generate_prime_ex(ret, bits, safe, add, rem, reinterpret_cast<BN_GENCB*>(cb));
-}
-
-static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, BIGNUM* p, int nchecks, jint cb) {
-    if (!oneValidHandle(env, p)) return JNI_FALSE;
-    Unique_BN_CTX ctx(BN_CTX_new());
-    return BN_is_prime_ex(p, nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
+static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, jlong p, int nchecks, jlong cb) {
+  if (!oneValidHandle(env, p)) return JNI_FALSE;
+  Unique_BN_CTX ctx(BN_CTX_new());
+  return BN_is_prime_ex(toBigNum(p), nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
 }
 
 static JNINativeMethod gMethods[] = {
-   NATIVE_METHOD(NativeBN, BN_add, "(III)Z"),
-   NATIVE_METHOD(NativeBN, BN_add_word, "(II)Z"),
-   NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZI)Z"),
-   NATIVE_METHOD(NativeBN, BN_bn2bin, "(I)[B"),
-   NATIVE_METHOD(NativeBN, BN_bn2dec, "(I)Ljava/lang/String;"),
-   NATIVE_METHOD(NativeBN, BN_bn2hex, "(I)Ljava/lang/String;"),
-   NATIVE_METHOD(NativeBN, BN_cmp, "(II)I"),
-   NATIVE_METHOD(NativeBN, BN_copy, "(II)Z"),
-   NATIVE_METHOD(NativeBN, BN_dec2bn, "(ILjava/lang/String;)I"),
-   NATIVE_METHOD(NativeBN, BN_div, "(IIII)Z"),
-   NATIVE_METHOD(NativeBN, BN_div_word, "(II)I"),
-   NATIVE_METHOD(NativeBN, BN_exp, "(III)Z"),
-   NATIVE_METHOD(NativeBN, BN_free, "(I)V"),
-   NATIVE_METHOD(NativeBN, BN_gcd, "(III)Z"),
-   NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(IIZIII)Z"),
-   NATIVE_METHOD(NativeBN, BN_hex2bn, "(ILjava/lang/String;)I"),
-   NATIVE_METHOD(NativeBN, BN_is_bit_set, "(II)Z"),
-   NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(III)Z"),
-   NATIVE_METHOD(NativeBN, BN_mod_exp, "(IIII)Z"),
-   NATIVE_METHOD(NativeBN, BN_mod_inverse, "(III)Z"),
-   NATIVE_METHOD(NativeBN, BN_mod_word, "(II)I"),
-   NATIVE_METHOD(NativeBN, BN_mul, "(III)Z"),
-   NATIVE_METHOD(NativeBN, BN_mul_word, "(II)Z"),
-   NATIVE_METHOD(NativeBN, BN_new, "()I"),
-   NATIVE_METHOD(NativeBN, BN_nnmod, "(III)Z"),
-   NATIVE_METHOD(NativeBN, BN_set_negative, "(II)V"),
-   NATIVE_METHOD(NativeBN, BN_shift, "(III)Z"),
-   NATIVE_METHOD(NativeBN, BN_sub, "(III)Z"),
-   NATIVE_METHOD(NativeBN, BN_sub_word, "(II)Z"),
-   NATIVE_METHOD(NativeBN, ERR_error_string, "(I)Ljava/lang/String;"),
-   NATIVE_METHOD(NativeBN, ERR_get_error, "()I"),
-   NATIVE_METHOD(NativeBN, bitLength, "(I)I"),
-   NATIVE_METHOD(NativeBN, bn2litEndInts, "(I)[I"),
-   NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZI)Z"),
-   NATIVE_METHOD(NativeBN, longInt, "(I)J"),
-   NATIVE_METHOD(NativeBN, modifyBit, "(III)Z"),
-   NATIVE_METHOD(NativeBN, putLongInt, "(IJ)Z"),
-   NATIVE_METHOD(NativeBN, putULongInt, "(IJZ)Z"),
-   NATIVE_METHOD(NativeBN, sign, "(I)I"),
-   NATIVE_METHOD(NativeBN, twosComp2bn, "([BII)Z"),
+   NATIVE_METHOD(NativeBN, BN_add, "(JJJ)V"),
+   NATIVE_METHOD(NativeBN, BN_add_word, "(JI)V"),
+   NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZJ)V"),
+   NATIVE_METHOD(NativeBN, BN_bn2bin, "(J)[B"),
+   NATIVE_METHOD(NativeBN, BN_bn2dec, "(J)Ljava/lang/String;"),
+   NATIVE_METHOD(NativeBN, BN_bn2hex, "(J)Ljava/lang/String;"),
+   NATIVE_METHOD(NativeBN, BN_cmp, "(JJ)I"),
+   NATIVE_METHOD(NativeBN, BN_copy, "(JJ)V"),
+   NATIVE_METHOD(NativeBN, BN_dec2bn, "(JLjava/lang/String;)I"),
+   NATIVE_METHOD(NativeBN, BN_div, "(JJJJ)V"),
+   NATIVE_METHOD(NativeBN, BN_exp, "(JJJ)V"),
+   NATIVE_METHOD(NativeBN, BN_free, "(J)V"),
+   NATIVE_METHOD(NativeBN, BN_gcd, "(JJJ)V"),
+   NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(JIZJJJ)V"),
+   NATIVE_METHOD(NativeBN, BN_hex2bn, "(JLjava/lang/String;)I"),
+   NATIVE_METHOD(NativeBN, BN_is_bit_set, "(JI)Z"),
+   NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(JIJ)Z"),
+   NATIVE_METHOD(NativeBN, BN_mod_exp, "(JJJJ)V"),
+   NATIVE_METHOD(NativeBN, BN_mod_inverse, "(JJJ)V"),
+   NATIVE_METHOD(NativeBN, BN_mod_word, "(JI)I"),
+   NATIVE_METHOD(NativeBN, BN_mul, "(JJJ)V"),
+   NATIVE_METHOD(NativeBN, BN_mul_word, "(JI)V"),
+   NATIVE_METHOD(NativeBN, BN_new, "()J"),
+   NATIVE_METHOD(NativeBN, BN_nnmod, "(JJJ)V"),
+   NATIVE_METHOD(NativeBN, BN_set_negative, "(JI)V"),
+   NATIVE_METHOD(NativeBN, BN_shift, "(JJI)V"),
+   NATIVE_METHOD(NativeBN, BN_sub, "(JJJ)V"),
+   NATIVE_METHOD(NativeBN, bitLength, "(J)I"),
+   NATIVE_METHOD(NativeBN, bn2litEndInts, "(J)[I"),
+   NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZJ)V"),
+   NATIVE_METHOD(NativeBN, longInt, "(J)J"),
+   NATIVE_METHOD(NativeBN, putLongInt, "(JJ)V"),
+   NATIVE_METHOD(NativeBN, putULongInt, "(JJZ)V"),
+   NATIVE_METHOD(NativeBN, sign, "(J)I"),
+   NATIVE_METHOD(NativeBN, twosComp2bn, "([BIJ)V"),
 };
 void register_java_math_NativeBN(JNIEnv* env) {
     jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
index e034c37..bb05193 100644
--- a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
+++ b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
@@ -21,7 +21,6 @@
 #include "JniConstants.h"
 #include "JniException.h"
 #include "ScopedJavaUnicodeString.h"
-#include "ScopedStringChars.h"
 #include "unicode/alphaindex.h"
 #include "unicode/uniset.h"
 
diff --git a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
new file mode 100644
index 0000000..65ace4e
--- /dev/null
+++ b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "DateIntervalFormat"
+
+#include "IcuUtilities.h"
+#include "JniConstants.h"
+#include "ScopedJavaUnicodeString.h"
+#include "UniquePtr.h"
+#include "cutils/log.h"
+#include "unicode/dtitvfmt.h"
+
+static jstring DateIntervalFormat_formatDateInterval(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName, jstring javaTzName, jlong fromDate, jlong toDate) {
+  Locale locale = getLocale(env, javaLocaleName);
+
+  ScopedJavaUnicodeString skeletonHolder(env, javaSkeleton);
+  if (!skeletonHolder.valid()) {
+    return NULL;
+  }
+
+  ScopedJavaUnicodeString tzNameHolder(env, javaTzName);
+  if (!tzNameHolder.valid()) {
+    return NULL;
+  }
+
+  UErrorCode status = U_ZERO_ERROR;
+  UniquePtr<DateIntervalFormat> formatter(DateIntervalFormat::createInstance(skeletonHolder.unicodeString(), locale, status));
+  if (maybeThrowIcuException(env, "DateIntervalFormat::createInstance", status)) {
+    return NULL;
+  }
+
+  formatter->adoptTimeZone(TimeZone::createTimeZone(tzNameHolder.unicodeString()));
+
+  DateInterval date_interval(fromDate, toDate);
+
+  UnicodeString result;
+  FieldPosition pos = 0;
+  formatter->format(&date_interval, result, pos, status);
+  if (maybeThrowIcuException(env, "DateIntervalFormat::format", status)) {
+      return NULL;
+  }
+
+  return env->NewString(result.getBuffer(), result.length());
+}
+
+static JNINativeMethod gMethods[] = {
+  NATIVE_METHOD(DateIntervalFormat, formatDateInterval, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JJ)Ljava/lang/String;"),
+};
+void register_libcore_icu_DateIntervalFormat(JNIEnv* env) {
+  jniRegisterNativeMethods(env, "libcore/icu/DateIntervalFormat", gMethods, NELEM(gMethods));
+}
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index 53a1241..40d6e04 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -394,9 +394,10 @@
   }
 
   void Up() {
-    locale_name_length_ = uloc_getParent(locale_name_, locale_name_, sizeof(locale_name_), &status_);
     if (locale_name_length_ == 0) {
       has_next_ = false;
+    } else {
+      locale_name_length_ = uloc_getParent(locale_name_, locale_name_, sizeof(locale_name_), &status_);
     }
   }
 
@@ -466,15 +467,7 @@
   if (U_FAILURE(status)) {
     return false;
   }
-  ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status));
-  if (U_FAILURE(status)) {
-    return false;
-  }
-  ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status));
-  if (U_FAILURE(status)) {
-    return false;
-  }
-  ScopedResourceBundle fields(ures_getByKey(gregorian.get(), "fields", NULL, &status));
+  ScopedResourceBundle fields(ures_getByKey(root.get(), "fields", NULL, &status));
   if (U_FAILURE(status)) {
     return false;
   }
@@ -699,7 +692,7 @@
     return result;
 }
 
-static jstring ICU_getBestDateTimePattern(JNIEnv* env, jclass, jstring javaPattern, jstring javaLocaleName) {
+static jstring ICU_getBestDateTimePattern(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName) {
   Locale locale = getLocale(env, javaLocaleName);
   UErrorCode status = U_ZERO_ERROR;
   DateTimePatternGenerator* generator = DateTimePatternGenerator::createInstance(locale, status);
@@ -707,11 +700,11 @@
     return NULL;
   }
 
-  ScopedJavaUnicodeString patternHolder(env, javaPattern);
-  if (!patternHolder.valid()) {
+  ScopedJavaUnicodeString skeletonHolder(env, javaSkeleton);
+  if (!skeletonHolder.valid()) {
     return NULL;
   }
-  UnicodeString result(generator->getBestPattern(patternHolder.unicodeString(), status));
+  UnicodeString result(generator->getBestPattern(skeletonHolder.unicodeString(), status));
   if (maybeThrowIcuException(env, "DateTimePatternGenerator::getBestPattern", status)) {
     return NULL;
   }
diff --git a/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp b/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
index c025a60..5d715c9 100644
--- a/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
+++ b/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
@@ -27,7 +27,7 @@
 
 // ICU documentation: http://icu-project.org/apiref/icu4c/classBreakIterator.html
 
-static BreakIterator* toBreakIterator(jint address) {
+static BreakIterator* toBreakIterator(jlong address) {
   return reinterpret_cast<BreakIterator*>(static_cast<uintptr_t>(address));
 }
 
@@ -39,7 +39,7 @@
  */
 class BreakIteratorAccessor {
  public:
-  BreakIteratorAccessor(JNIEnv* env, jint address, jstring javaInput, bool reset) {
+  BreakIteratorAccessor(JNIEnv* env, jlong address, jstring javaInput, bool reset) {
     init(env, address);
     mJavaInput = javaInput;
 
@@ -64,7 +64,7 @@
     }
   }
 
-  BreakIteratorAccessor(JNIEnv* env, jint address) {
+  BreakIteratorAccessor(JNIEnv* env, jlong address) {
     init(env, address);
   }
 
@@ -85,7 +85,7 @@
   }
 
  private:
-  void init(JNIEnv* env, jint address) {
+  void init(JNIEnv* env, jlong address) {
     mEnv = env;
     mJavaInput = NULL;
     mBreakIterator = toBreakIterator(address);
@@ -119,26 +119,26 @@
   } \
   return reinterpret_cast<uintptr_t>(it)
 
-static jint NativeBreakIterator_cloneImpl(JNIEnv* env, jclass, jint address) {
+static jint NativeBreakIterator_cloneImpl(JNIEnv* env, jclass, jlong address) {
   BreakIteratorAccessor it(env, address);
   return reinterpret_cast<uintptr_t>(it->clone());
 }
 
-static void NativeBreakIterator_closeImpl(JNIEnv*, jclass, jint address) {
+static void NativeBreakIterator_closeImpl(JNIEnv*, jclass, jlong address) {
   delete toBreakIterator(address);
 }
 
-static jint NativeBreakIterator_currentImpl(JNIEnv* env, jclass, jint address, jstring javaInput) {
+static jint NativeBreakIterator_currentImpl(JNIEnv* env, jclass, jlong address, jstring javaInput) {
   BreakIteratorAccessor it(env, address, javaInput, false);
   return it->current();
 }
 
-static jint NativeBreakIterator_firstImpl(JNIEnv* env, jclass, jint address, jstring javaInput) {
+static jint NativeBreakIterator_firstImpl(JNIEnv* env, jclass, jlong address, jstring javaInput) {
   BreakIteratorAccessor it(env, address, javaInput, false);
   return it->first();
 }
 
-static jint NativeBreakIterator_followingImpl(JNIEnv* env, jclass, jint address, jstring javaInput, jint offset) {
+static jint NativeBreakIterator_followingImpl(JNIEnv* env, jclass, jlong address, jstring javaInput, jint offset) {
   BreakIteratorAccessor it(env, address, javaInput, false);
   return it->following(offset);
 }
@@ -159,17 +159,17 @@
   MAKE_BREAK_ITERATOR_INSTANCE(BreakIterator::createWordInstance);
 }
 
-static jboolean NativeBreakIterator_isBoundaryImpl(JNIEnv* env, jclass, jint address, jstring javaInput, jint offset) {
+static jboolean NativeBreakIterator_isBoundaryImpl(JNIEnv* env, jclass, jlong address, jstring javaInput, jint offset) {
   BreakIteratorAccessor it(env, address, javaInput, false);
   return it->isBoundary(offset);
 }
 
-static jint NativeBreakIterator_lastImpl(JNIEnv* env, jclass, jint address, jstring javaInput) {
+static jint NativeBreakIterator_lastImpl(JNIEnv* env, jclass, jlong address, jstring javaInput) {
   BreakIteratorAccessor it(env, address, javaInput, false);
   return it->last();
 }
 
-static jint NativeBreakIterator_nextImpl(JNIEnv* env, jclass, jint address, jstring javaInput, jint n) {
+static jint NativeBreakIterator_nextImpl(JNIEnv* env, jclass, jlong address, jstring javaInput, jint n) {
   BreakIteratorAccessor it(env, address, javaInput, false);
   if (n < 0) {
     while (n++ < -1) {
@@ -187,36 +187,36 @@
   return -1;
 }
 
-static jint NativeBreakIterator_precedingImpl(JNIEnv* env, jclass, jint address, jstring javaInput, jint offset) {
+static jint NativeBreakIterator_precedingImpl(JNIEnv* env, jclass, jlong address, jstring javaInput, jint offset) {
   BreakIteratorAccessor it(env, address, javaInput, false);
   return it->preceding(offset);
 }
 
-static jint NativeBreakIterator_previousImpl(JNIEnv* env, jclass, jint address, jstring javaInput) {
+static jint NativeBreakIterator_previousImpl(JNIEnv* env, jclass, jlong address, jstring javaInput) {
   BreakIteratorAccessor it(env, address, javaInput, false);
   return it->previous();
 }
 
-static void NativeBreakIterator_setTextImpl(JNIEnv* env, jclass, jint address, jstring javaInput) {
+static void NativeBreakIterator_setTextImpl(JNIEnv* env, jclass, jlong address, jstring javaInput) {
   BreakIteratorAccessor it(env, address, javaInput, true);
 }
 
 static JNINativeMethod gMethods[] = {
-  NATIVE_METHOD(NativeBreakIterator, cloneImpl, "(I)I"),
-  NATIVE_METHOD(NativeBreakIterator, closeImpl, "(I)V"),
-  NATIVE_METHOD(NativeBreakIterator, currentImpl, "(ILjava/lang/String;)I"),
-  NATIVE_METHOD(NativeBreakIterator, firstImpl, "(ILjava/lang/String;)I"),
-  NATIVE_METHOD(NativeBreakIterator, followingImpl, "(ILjava/lang/String;I)I"),
-  NATIVE_METHOD(NativeBreakIterator, getCharacterInstanceImpl, "(Ljava/lang/String;)I"),
-  NATIVE_METHOD(NativeBreakIterator, getLineInstanceImpl, "(Ljava/lang/String;)I"),
-  NATIVE_METHOD(NativeBreakIterator, getSentenceInstanceImpl, "(Ljava/lang/String;)I"),
-  NATIVE_METHOD(NativeBreakIterator, getWordInstanceImpl, "(Ljava/lang/String;)I"),
-  NATIVE_METHOD(NativeBreakIterator, isBoundaryImpl, "(ILjava/lang/String;I)Z"),
-  NATIVE_METHOD(NativeBreakIterator, lastImpl, "(ILjava/lang/String;)I"),
-  NATIVE_METHOD(NativeBreakIterator, nextImpl, "(ILjava/lang/String;I)I"),
-  NATIVE_METHOD(NativeBreakIterator, precedingImpl, "(ILjava/lang/String;I)I"),
-  NATIVE_METHOD(NativeBreakIterator, previousImpl, "(ILjava/lang/String;)I"),
-  NATIVE_METHOD(NativeBreakIterator, setTextImpl, "(ILjava/lang/String;)V"),
+  NATIVE_METHOD(NativeBreakIterator, cloneImpl, "(J)J"),
+  NATIVE_METHOD(NativeBreakIterator, closeImpl, "(J)V"),
+  NATIVE_METHOD(NativeBreakIterator, currentImpl, "(JLjava/lang/String;)I"),
+  NATIVE_METHOD(NativeBreakIterator, firstImpl, "(JLjava/lang/String;)I"),
+  NATIVE_METHOD(NativeBreakIterator, followingImpl, "(JLjava/lang/String;I)I"),
+  NATIVE_METHOD(NativeBreakIterator, getCharacterInstanceImpl, "(Ljava/lang/String;)J"),
+  NATIVE_METHOD(NativeBreakIterator, getLineInstanceImpl, "(Ljava/lang/String;)J"),
+  NATIVE_METHOD(NativeBreakIterator, getSentenceInstanceImpl, "(Ljava/lang/String;)J"),
+  NATIVE_METHOD(NativeBreakIterator, getWordInstanceImpl, "(Ljava/lang/String;)J"),
+  NATIVE_METHOD(NativeBreakIterator, isBoundaryImpl, "(JLjava/lang/String;I)Z"),
+  NATIVE_METHOD(NativeBreakIterator, lastImpl, "(JLjava/lang/String;)I"),
+  NATIVE_METHOD(NativeBreakIterator, nextImpl, "(JLjava/lang/String;I)I"),
+  NATIVE_METHOD(NativeBreakIterator, precedingImpl, "(JLjava/lang/String;I)I"),
+  NATIVE_METHOD(NativeBreakIterator, previousImpl, "(JLjava/lang/String;)I"),
+  NATIVE_METHOD(NativeBreakIterator, setTextImpl, "(JLjava/lang/String;)V"),
 };
 void register_libcore_icu_NativeBreakIterator(JNIEnv* env) {
   jniRegisterNativeMethods(env, "libcore/icu/NativeBreakIterator", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/libcore_icu_NativeCollation.cpp b/luni/src/main/native/libcore_icu_NativeCollation.cpp
index 98a78ea..9ac7745 100644
--- a/luni/src/main/native/libcore_icu_NativeCollation.cpp
+++ b/luni/src/main/native/libcore_icu_NativeCollation.cpp
@@ -20,23 +20,23 @@
 #include "unicode/ucol.h"
 #include "unicode/ucoleitr.h"
 
-static UCollator* toCollator(jint address) {
+static UCollator* toCollator(jlong address) {
     return reinterpret_cast<UCollator*>(static_cast<uintptr_t>(address));
 }
 
-static UCollationElements* toCollationElements(jint address) {
+static UCollationElements* toCollationElements(jlong address) {
     return reinterpret_cast<UCollationElements*>(static_cast<uintptr_t>(address));
 }
 
-static void NativeCollation_closeCollator(JNIEnv*, jclass, jint address) {
+static void NativeCollation_closeCollator(JNIEnv*, jclass, jlong address) {
     ucol_close(toCollator(address));
 }
 
-static void NativeCollation_closeElements(JNIEnv*, jclass, jint address) {
+static void NativeCollation_closeElements(JNIEnv*, jclass, jlong address) {
     ucol_closeElements(toCollationElements(address));
 }
 
-static jint NativeCollation_compare(JNIEnv* env, jclass, jint address, jstring javaLhs, jstring javaRhs) {
+static jint NativeCollation_compare(JNIEnv* env, jclass, jlong address, jstring javaLhs, jstring javaRhs) {
     ScopedStringChars lhs(env, javaLhs);
     if (lhs.get() == NULL) {
         return 0;
@@ -48,14 +48,14 @@
     return ucol_strcoll(toCollator(address), lhs.get(), lhs.size(), rhs.get(), rhs.size());
 }
 
-static jint NativeCollation_getAttribute(JNIEnv* env, jclass, jint address, jint type) {
+static jint NativeCollation_getAttribute(JNIEnv* env, jclass, jlong address, jint type) {
     UErrorCode status = U_ZERO_ERROR;
     jint result = ucol_getAttribute(toCollator(address), (UColAttribute) type, &status);
     maybeThrowIcuException(env, "ucol_getAttribute", status);
     return result;
 }
 
-static jint NativeCollation_getCollationElementIterator(JNIEnv* env, jclass, jint address, jstring javaSource) {
+static jlong NativeCollation_getCollationElementIterator(JNIEnv* env, jclass, jlong address, jstring javaSource) {
     ScopedStringChars source(env, javaSource);
     if (source.get() == NULL) {
         return -1;
@@ -63,24 +63,24 @@
     UErrorCode status = U_ZERO_ERROR;
     UCollationElements* result = ucol_openElements(toCollator(address), source.get(), source.size(), &status);
     maybeThrowIcuException(env, "ucol_openElements", status);
-    return static_cast<jint>(reinterpret_cast<uintptr_t>(result));
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(result));
 }
 
-static jint NativeCollation_getMaxExpansion(JNIEnv*, jclass, jint address, jint order) {
+static jint NativeCollation_getMaxExpansion(JNIEnv*, jclass, jlong address, jint order) {
     return ucol_getMaxExpansion(toCollationElements(address), order);
 }
 
-static jint NativeCollation_getOffset(JNIEnv*, jclass, jint address) {
+static jint NativeCollation_getOffset(JNIEnv*, jclass, jlong address) {
     return ucol_getOffset(toCollationElements(address));
 }
 
-static jstring NativeCollation_getRules(JNIEnv* env, jclass, jint address) {
+static jstring NativeCollation_getRules(JNIEnv* env, jclass, jlong address) {
     int32_t length = 0;
     const UChar* rules = ucol_getRules(toCollator(address), &length);
     return env->NewString(rules, length);
 }
 
-static jbyteArray NativeCollation_getSortKey(JNIEnv* env, jclass, jint address, jstring javaSource) {
+static jbyteArray NativeCollation_getSortKey(JNIEnv* env, jclass, jlong address, jstring javaSource) {
     ScopedStringChars source(env, javaSource);
     if (source.get() == NULL) {
         return NULL;
@@ -104,14 +104,14 @@
     return result;
 }
 
-static jint NativeCollation_next(JNIEnv* env, jclass, jint address) {
+static jint NativeCollation_next(JNIEnv* env, jclass, jlong address) {
     UErrorCode status = U_ZERO_ERROR;
     jint result = ucol_next(toCollationElements(address), &status);
     maybeThrowIcuException(env, "ucol_next", status);
     return result;
 }
 
-static jint NativeCollation_openCollator(JNIEnv* env, jclass, jstring localeName) {
+static jlong NativeCollation_openCollator(JNIEnv* env, jclass, jstring localeName) {
     ScopedUtfChars localeChars(env, localeName);
     if (localeChars.c_str() == NULL) {
         return 0;
@@ -119,10 +119,10 @@
     UErrorCode status = U_ZERO_ERROR;
     UCollator* c = ucol_open(localeChars.c_str(), &status);
     maybeThrowIcuException(env, "ucol_open", status);
-    return static_cast<jint>(reinterpret_cast<uintptr_t>(c));
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(c));
 }
 
-static jint NativeCollation_openCollatorFromRules(JNIEnv* env, jclass, jstring javaRules, jint mode, jint strength) {
+static jlong NativeCollation_openCollatorFromRules(JNIEnv* env, jclass, jstring javaRules, jint mode, jint strength) {
     ScopedStringChars rules(env, javaRules);
     if (rules.get() == NULL) {
         return -1;
@@ -131,41 +131,41 @@
     UCollator* c = ucol_openRules(rules.get(), rules.size(),
             UColAttributeValue(mode), UCollationStrength(strength), NULL, &status);
     maybeThrowIcuException(env, "ucol_openRules", status);
-    return static_cast<jint>(reinterpret_cast<uintptr_t>(c));
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(c));
 }
 
-static jint NativeCollation_previous(JNIEnv* env, jclass, jint address) {
+static jint NativeCollation_previous(JNIEnv* env, jclass, jlong address) {
     UErrorCode status = U_ZERO_ERROR;
     jint result = ucol_previous(toCollationElements(address), &status);
     maybeThrowIcuException(env, "ucol_previous", status);
     return result;
 }
 
-static void NativeCollation_reset(JNIEnv*, jclass, jint address) {
+static void NativeCollation_reset(JNIEnv*, jclass, jlong address) {
     ucol_reset(toCollationElements(address));
 }
 
-static jint NativeCollation_safeClone(JNIEnv* env, jclass, jint address) {
+static jlong NativeCollation_safeClone(JNIEnv* env, jclass, jlong address) {
     UErrorCode status = U_ZERO_ERROR;
     jint bufferSize = U_COL_SAFECLONE_BUFFERSIZE;
     UCollator* c = ucol_safeClone(toCollator(address), NULL, &bufferSize, &status);
     maybeThrowIcuException(env, "ucol_safeClone", status);
-    return static_cast<jint>(reinterpret_cast<uintptr_t>(c));
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(c));
 }
 
-static void NativeCollation_setAttribute(JNIEnv* env, jclass, jint address, jint type, jint value) {
+static void NativeCollation_setAttribute(JNIEnv* env, jclass, jlong address, jint type, jint value) {
     UErrorCode status = U_ZERO_ERROR;
     ucol_setAttribute(toCollator(address), (UColAttribute)type, (UColAttributeValue)value, &status);
     maybeThrowIcuException(env, "ucol_setAttribute", status);
 }
 
-static void NativeCollation_setOffset(JNIEnv* env, jclass, jint address, jint offset) {
+static void NativeCollation_setOffset(JNIEnv* env, jclass, jlong address, jint offset) {
     UErrorCode status = U_ZERO_ERROR;
     ucol_setOffset(toCollationElements(address), offset, &status);
     maybeThrowIcuException(env, "ucol_setOffset", status);
 }
 
-static void NativeCollation_setText(JNIEnv* env, jclass, jint address, jstring javaSource) {
+static void NativeCollation_setText(JNIEnv* env, jclass, jlong address, jstring javaSource) {
     ScopedStringChars source(env, javaSource);
     if (source.get() == NULL) {
         return;
@@ -176,24 +176,24 @@
 }
 
 static JNINativeMethod gMethods[] = {
-    NATIVE_METHOD(NativeCollation, closeCollator, "(I)V"),
-    NATIVE_METHOD(NativeCollation, closeElements, "(I)V"),
-    NATIVE_METHOD(NativeCollation, compare, "(ILjava/lang/String;Ljava/lang/String;)I"),
-    NATIVE_METHOD(NativeCollation, getAttribute, "(II)I"),
-    NATIVE_METHOD(NativeCollation, getCollationElementIterator, "(ILjava/lang/String;)I"),
-    NATIVE_METHOD(NativeCollation, getMaxExpansion, "(II)I"),
-    NATIVE_METHOD(NativeCollation, getOffset, "(I)I"),
-    NATIVE_METHOD(NativeCollation, getRules, "(I)Ljava/lang/String;"),
-    NATIVE_METHOD(NativeCollation, getSortKey, "(ILjava/lang/String;)[B"),
-    NATIVE_METHOD(NativeCollation, next, "(I)I"),
-    NATIVE_METHOD(NativeCollation, openCollator, "(Ljava/lang/String;)I"),
-    NATIVE_METHOD(NativeCollation, openCollatorFromRules, "(Ljava/lang/String;II)I"),
-    NATIVE_METHOD(NativeCollation, previous, "(I)I"),
-    NATIVE_METHOD(NativeCollation, reset, "(I)V"),
-    NATIVE_METHOD(NativeCollation, safeClone, "(I)I"),
-    NATIVE_METHOD(NativeCollation, setAttribute, "(III)V"),
-    NATIVE_METHOD(NativeCollation, setOffset, "(II)V"),
-    NATIVE_METHOD(NativeCollation, setText, "(ILjava/lang/String;)V"),
+    NATIVE_METHOD(NativeCollation, closeCollator, "(J)V"),
+    NATIVE_METHOD(NativeCollation, closeElements, "(J)V"),
+    NATIVE_METHOD(NativeCollation, compare, "(JLjava/lang/String;Ljava/lang/String;)I"),
+    NATIVE_METHOD(NativeCollation, getAttribute, "(JI)I"),
+    NATIVE_METHOD(NativeCollation, getCollationElementIterator, "(JLjava/lang/String;)I"),
+    NATIVE_METHOD(NativeCollation, getMaxExpansion, "(JI)I"),
+    NATIVE_METHOD(NativeCollation, getOffset, "(J)I"),
+    NATIVE_METHOD(NativeCollation, getRules, "(J)Ljava/lang/String;"),
+    NATIVE_METHOD(NativeCollation, getSortKey, "(JLjava/lang/String;)[B"),
+    NATIVE_METHOD(NativeCollation, next, "(J)I"),
+    NATIVE_METHOD(NativeCollation, openCollator, "(Ljava/lang/String;)J"),
+    NATIVE_METHOD(NativeCollation, openCollatorFromRules, "(Ljava/lang/String;II)J"),
+    NATIVE_METHOD(NativeCollation, previous, "(J)I"),
+    NATIVE_METHOD(NativeCollation, reset, "(J)V"),
+    NATIVE_METHOD(NativeCollation, safeClone, "(J)J"),
+    NATIVE_METHOD(NativeCollation, setAttribute, "(JII)V"),
+    NATIVE_METHOD(NativeCollation, setOffset, "(JI)V"),
+    NATIVE_METHOD(NativeCollation, setText, "(JLjava/lang/String;)V"),
 };
 void register_libcore_icu_NativeCollation(JNIEnv* env) {
     jniRegisterNativeMethods(env, "libcore/icu/NativeCollation", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index 24dfa6f..fae56b7 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -230,28 +230,6 @@
     return (cnv != NULL) ? ((ucnv_getMaxCharSize(cnv) + ucnv_getMinCharSize(cnv)) / 2.0) : -1;
 }
 
-static jboolean NativeConverter_canEncode(JNIEnv*, jclass, jlong address, jint codeUnit) {
-    UErrorCode errorCode = U_ZERO_ERROR;
-    UConverter* cnv = toUConverter(address);
-    if (cnv == NULL) {
-        return JNI_FALSE;
-    }
-
-    UChar srcBuffer[3];
-    const UChar* src = &srcBuffer[0];
-    const UChar* srcLimit = (codeUnit < 0x10000) ? &src[1] : &src[2];
-
-    char dstBuffer[5];
-    char* dst = &dstBuffer[0];
-    const char* dstLimit = &dstBuffer[4];
-
-    int i = 0;
-    UTF_APPEND_CHAR(&srcBuffer[0], i, 2, codeUnit);
-
-    ucnv_fromUnicode(cnv, &dst, dstLimit, &src, srcLimit, NULL, TRUE, &errorCode);
-    return U_SUCCESS(errorCode);
-}
-
 /*
  * If a charset listed in the IANA Charset Registry is supported by an implementation
  * of the Java platform then its canonical name must be the name listed in the registry.
@@ -620,7 +598,6 @@
 }
 
 static JNINativeMethod gMethods[] = {
-    NATIVE_METHOD(NativeConverter, canEncode, "(JI)Z"),
     NATIVE_METHOD(NativeConverter, charsetForName, "(Ljava/lang/String;)Ljava/nio/charset/Charset;"),
     NATIVE_METHOD(NativeConverter, closeConverter, "(J)V"),
     NATIVE_METHOD(NativeConverter, contains, "(Ljava/lang/String;Ljava/lang/String;)Z"),
diff --git a/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp b/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
index efed954..88e6780 100644
--- a/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
+++ b/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
@@ -343,7 +343,7 @@
 
 static JNINativeMethod gMethods[] = {
     NATIVE_METHOD(NativeDecimalFormat, applyPatternImpl, "(JZLjava/lang/String;)V"),
-    NATIVE_METHOD(NativeDecimalFormat, cloneImpl, "(J)I"),
+    NATIVE_METHOD(NativeDecimalFormat, cloneImpl, "(J)J"),
     NATIVE_METHOD(NativeDecimalFormat, close, "(J)V"),
     NATIVE_METHOD(NativeDecimalFormat, formatDouble, "(JDLlibcore/icu/NativeDecimalFormat$FieldPositionIterator;)[C"),
     NATIVE_METHOD(NativeDecimalFormat, formatLong, "(JJLlibcore/icu/NativeDecimalFormat$FieldPositionIterator;)[C"),
diff --git a/luni/src/main/native/libcore_icu_NativePluralRules.cpp b/luni/src/main/native/libcore_icu_NativePluralRules.cpp
index 571ba6d..8910a8c 100644
--- a/luni/src/main/native/libcore_icu_NativePluralRules.cpp
+++ b/luni/src/main/native/libcore_icu_NativePluralRules.cpp
@@ -25,15 +25,15 @@
 
 #include <string>
 
-static PluralRules* toPluralRules(jint address) {
+static PluralRules* toPluralRules(jlong address) {
     return reinterpret_cast<PluralRules*>(static_cast<uintptr_t>(address));
 }
 
-static void NativePluralRules_finalizeImpl(JNIEnv*, jclass, jint address) {
+static void NativePluralRules_finalizeImpl(JNIEnv*, jclass, jlong address) {
     delete toPluralRules(address);
 }
 
-static jint NativePluralRules_forLocaleImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
+static jlong NativePluralRules_forLocaleImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
     // The icu4c PluralRules returns a "other: n" default rule for the deprecated locales Java uses.
     // Work around this by translating back to the current language codes.
     std::string localeName(ScopedUtfChars(env, javaLocaleName).c_str());
@@ -55,7 +55,7 @@
     return reinterpret_cast<uintptr_t>(result);
 }
 
-static jint NativePluralRules_quantityForIntImpl(JNIEnv*, jclass, jint address, jint value) {
+static jint NativePluralRules_quantityForIntImpl(JNIEnv*, jclass, jlong address, jint value) {
     UnicodeString keyword = toPluralRules(address)->select(value);
     if (keyword == "zero") {
         return 0;
@@ -73,9 +73,9 @@
 }
 
 static JNINativeMethod gMethods[] = {
-    NATIVE_METHOD(NativePluralRules, finalizeImpl, "(I)V"),
-    NATIVE_METHOD(NativePluralRules, forLocaleImpl, "(Ljava/lang/String;)I"),
-    NATIVE_METHOD(NativePluralRules, quantityForIntImpl, "(II)I"),
+    NATIVE_METHOD(NativePluralRules, finalizeImpl, "(J)V"),
+    NATIVE_METHOD(NativePluralRules, forLocaleImpl, "(Ljava/lang/String;)J"),
+    NATIVE_METHOD(NativePluralRules, quantityForIntImpl, "(JI)I"),
 };
 void register_libcore_icu_NativePluralRules(JNIEnv* env) {
     jniRegisterNativeMethods(env, "libcore/icu/NativePluralRules", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/libcore_icu_Transliterator.cpp b/luni/src/main/native/libcore_icu_Transliterator.cpp
index 282e642..f2a54cb 100644
--- a/luni/src/main/native/libcore_icu_Transliterator.cpp
+++ b/luni/src/main/native/libcore_icu_Transliterator.cpp
@@ -21,7 +21,6 @@
 #include "JniConstants.h"
 #include "JniException.h"
 #include "ScopedJavaUnicodeString.h"
-#include "ScopedStringChars.h"
 #include "unicode/translit.h"
 
 static Transliterator* fromPeer(jlong peer) {
diff --git a/luni/src/main/native/libcore_io_OsConstants.cpp b/luni/src/main/native/libcore_io_OsConstants.cpp
index 56a159f..8f1f506 100644
--- a/luni/src/main/native/libcore_io_OsConstants.cpp
+++ b/luni/src/main/native/libcore_io_OsConstants.cpp
@@ -27,6 +27,7 @@
 #include <poll.h>
 #include <signal.h>
 #include <stdlib.h>
+#include <sys/capability.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/socket.h>
@@ -55,6 +56,43 @@
 #endif
     initConstant(env, c, "AI_PASSIVE", AI_PASSIVE);
     initConstant(env, c, "AI_V4MAPPED", AI_V4MAPPED);
+    initConstant(env, c, "CAP_AUDIT_CONTROL", CAP_AUDIT_CONTROL);
+    initConstant(env, c, "CAP_AUDIT_WRITE", CAP_AUDIT_WRITE);
+    initConstant(env, c, "CAP_CHOWN", CAP_CHOWN);
+    initConstant(env, c, "CAP_DAC_OVERRIDE", CAP_DAC_OVERRIDE);
+    initConstant(env, c, "CAP_DAC_READ_SEARCH", CAP_DAC_READ_SEARCH);
+    initConstant(env, c, "CAP_FOWNER", CAP_FOWNER);
+    initConstant(env, c, "CAP_FSETID", CAP_FSETID);
+    initConstant(env, c, "CAP_IPC_LOCK", CAP_IPC_LOCK);
+    initConstant(env, c, "CAP_IPC_OWNER", CAP_IPC_OWNER);
+    initConstant(env, c, "CAP_KILL", CAP_KILL);
+    initConstant(env, c, "CAP_LAST_CAP", CAP_LAST_CAP);
+    initConstant(env, c, "CAP_LEASE", CAP_LEASE);
+    initConstant(env, c, "CAP_LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE);
+    initConstant(env, c, "CAP_MAC_ADMIN", CAP_MAC_ADMIN);
+    initConstant(env, c, "CAP_MAC_OVERRIDE", CAP_MAC_OVERRIDE);
+    initConstant(env, c, "CAP_MKNOD", CAP_MKNOD);
+    initConstant(env, c, "CAP_NET_ADMIN", CAP_NET_ADMIN);
+    initConstant(env, c, "CAP_NET_BIND_SERVICE", CAP_NET_BIND_SERVICE);
+    initConstant(env, c, "CAP_NET_BROADCAST", CAP_NET_BROADCAST);
+    initConstant(env, c, "CAP_NET_RAW", CAP_NET_RAW);
+    initConstant(env, c, "CAP_SETFCAP", CAP_SETFCAP);
+    initConstant(env, c, "CAP_SETGID", CAP_SETGID);
+    initConstant(env, c, "CAP_SETPCAP", CAP_SETPCAP);
+    initConstant(env, c, "CAP_SETUID", CAP_SETUID);
+    initConstant(env, c, "CAP_SYS_ADMIN", CAP_SYS_ADMIN);
+    initConstant(env, c, "CAP_SYS_BOOT", CAP_SYS_BOOT);
+    initConstant(env, c, "CAP_SYS_CHROOT", CAP_SYS_CHROOT);
+    initConstant(env, c, "CAP_SYSLOG", CAP_SYSLOG);
+    initConstant(env, c, "CAP_SYS_MODULE", CAP_SYS_MODULE);
+    initConstant(env, c, "CAP_SYS_NICE", CAP_SYS_NICE);
+    initConstant(env, c, "CAP_SYS_PACCT", CAP_SYS_PACCT);
+    initConstant(env, c, "CAP_SYS_PTRACE", CAP_SYS_PTRACE);
+    initConstant(env, c, "CAP_SYS_RAWIO", CAP_SYS_RAWIO);
+    initConstant(env, c, "CAP_SYS_RESOURCE", CAP_SYS_RESOURCE);
+    initConstant(env, c, "CAP_SYS_TIME", CAP_SYS_TIME);
+    initConstant(env, c, "CAP_SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG);
+    initConstant(env, c, "CAP_WAKE_ALARM", CAP_WAKE_ALARM);
     initConstant(env, c, "E2BIG", E2BIG);
     initConstant(env, c, "EACCES", EACCES);
     initConstant(env, c, "EADDRINUSE", EADDRINUSE);
@@ -203,6 +241,7 @@
 #endif
     initConstant(env, c, "IFF_UP", IFF_UP);
     initConstant(env, c, "IPPROTO_ICMP", IPPROTO_ICMP);
+    initConstant(env, c, "IPPROTO_ICMPV6", IPPROTO_ICMPV6);
     initConstant(env, c, "IPPROTO_IP", IPPROTO_IP);
     initConstant(env, c, "IPPROTO_IPV6", IPPROTO_IPV6);
     initConstant(env, c, "IPPROTO_RAW", IPPROTO_RAW);
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index 1daa83d..7093a68 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "Posix"
 
 #include "AsynchronousSocketCloseMonitor.h"
+#include "ExecStrings.h"
 #include "JNIHelp.h"
 #include "JniConstants.h"
 #include "JniException.h"
@@ -36,7 +37,6 @@
 #include <net/if.h>
 #include <netdb.h>
 #include <netinet/in.h>
-#include <netinet/in.h>
 #include <poll.h>
 #include <pwd.h>
 #include <signal.h>
@@ -44,8 +44,8 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/socket.h>
-#include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/syscall.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/uio.h>
@@ -245,26 +245,28 @@
             static_cast<jlong>(sb.st_blocks));
 }
 
-static jobject makeStructStatFs(JNIEnv* env, const struct statfs& sb) {
+static jobject makeStructStatVfs(JNIEnv* env, const struct statvfs& sb) {
 #if defined(__APPLE__)
     // Mac OS has no f_namelen field in struct statfs.
     jlong max_name_length = 255; // __DARWIN_MAXNAMLEN
 #else
-    // Until Mac OS 10.7, these were 32-bit fields.
-    STATIC_ASSERT(sizeof(sb.f_bavail) == sizeof(jlong), statfs_not_64_bit);
-    STATIC_ASSERT(sizeof(sb.f_bfree) == sizeof(jlong), statfs_not_64_bit);
-    STATIC_ASSERT(sizeof(sb.f_blocks) == sizeof(jlong), statfs_not_64_bit);
-
-    jlong max_name_length = static_cast<jlong>(sb.f_namelen);
+    jlong max_name_length = static_cast<jlong>(sb.f_namemax);
 #endif
 
-    static jmethodID ctor = env->GetMethodID(JniConstants::structStatFsClass, "<init>",
-            "(JJJJJJJJ)V");
-    return env->NewObject(JniConstants::structStatFsClass, ctor, static_cast<jlong>(sb.f_bsize),
-            static_cast<jlong>(sb.f_blocks), static_cast<jlong>(sb.f_bfree),
-            static_cast<jlong>(sb.f_bavail), static_cast<jlong>(sb.f_files),
-            static_cast<jlong>(sb.f_ffree), max_name_length,
-            static_cast<jlong>(sb.f_frsize));
+    static jmethodID ctor = env->GetMethodID(JniConstants::structStatVfsClass, "<init>",
+            "(JJJJJJJJJJJ)V");
+    return env->NewObject(JniConstants::structStatVfsClass, ctor,
+                          static_cast<jlong>(sb.f_bsize),
+                          static_cast<jlong>(sb.f_frsize),
+                          static_cast<jlong>(sb.f_blocks),
+                          static_cast<jlong>(sb.f_bfree),
+                          static_cast<jlong>(sb.f_bavail),
+                          static_cast<jlong>(sb.f_files),
+                          static_cast<jlong>(sb.f_ffree),
+                          static_cast<jlong>(sb.f_favail),
+                          static_cast<jlong>(sb.f_fsid),
+                          static_cast<jlong>(sb.f_flag),
+                          max_name_length);
 }
 
 static jobject makeStructLinger(JNIEnv* env, const struct linger& l) {
@@ -357,11 +359,6 @@
 public:
     Passwd(JNIEnv* env) : mEnv(env), mResult(NULL) {
         mBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX);
-        if (mBufferSize == -1UL) {
-            // We're probably on bionic, where 1KiB should be enough for anyone.
-            // TODO: fix bionic to return 1024 like glibc.
-            mBufferSize = 1024;
-        }
         mBuffer.reset(new char[mBufferSize]);
     }
 
@@ -493,12 +490,10 @@
         return;
     }
 
-    char** argv = convertStrings(env, javaArgv);
-    char** envp = convertStrings(env, javaEnvp);
-    execve(path.c_str(), argv, envp);
+    ExecStrings argv(env, javaArgv);
+    ExecStrings envp(env, javaEnvp);
+    execve(path.c_str(), argv.get(), envp.get());
 
-    freeStrings(env, javaArgv, argv);
-    freeStrings(env, javaEnvp, envp);
     throwErrnoException(env, "execve");
 }
 
@@ -508,10 +503,9 @@
         return;
     }
 
-    char** argv = convertStrings(env, javaArgv);
-    execv(path.c_str(), argv);
+    ExecStrings argv(env, javaArgv);
+    execv(path.c_str(), argv.get());
 
-    freeStrings(env, javaArgv, argv);
     throwErrnoException(env, "execv");
 }
 
@@ -578,15 +572,15 @@
     return makeStructStat(env, sb);
 }
 
-static jobject Posix_fstatfs(JNIEnv* env, jobject, jobject javaFd) {
+static jobject Posix_fstatvfs(JNIEnv* env, jobject, jobject javaFd) {
     int fd = jniGetFDFromFileDescriptor(env, javaFd);
-    struct statfs sb;
-    int rc = TEMP_FAILURE_RETRY(fstatfs(fd, &sb));
+    struct statvfs sb;
+    int rc = TEMP_FAILURE_RETRY(fstatvfs(fd, &sb));
     if (rc == -1) {
-        throwErrnoException(env, "fstatfs");
+        throwErrnoException(env, "fstatvfs");
         return NULL;
     }
-    return makeStructStatFs(env, sb);
+    return makeStructStatVfs(env, sb);
 }
 
 static void Posix_fsync(JNIEnv* env, jobject, jobject javaFd) {
@@ -804,6 +798,11 @@
   return makeStructUcred(env, u);
 }
 
+static jint Posix_gettid(JNIEnv*, jobject) {
+  // Neither bionic nor glibc exposes gettid(2).
+  return syscall(__NR_gettid);
+}
+
 static jint Posix_getuid(JNIEnv*, jobject) {
     return getuid();
 }
@@ -1260,18 +1259,18 @@
     return doStat(env, javaPath, false);
 }
 
-static jobject Posix_statfs(JNIEnv* env, jobject, jstring javaPath) {
+static jobject Posix_statvfs(JNIEnv* env, jobject, jstring javaPath) {
     ScopedUtfChars path(env, javaPath);
     if (path.c_str() == NULL) {
         return NULL;
     }
-    struct statfs sb;
-    int rc = TEMP_FAILURE_RETRY(statfs(path.c_str(), &sb));
+    struct statvfs sb;
+    int rc = TEMP_FAILURE_RETRY(statvfs(path.c_str(), &sb));
     if (rc == -1) {
-        throwErrnoException(env, "statfs");
+        throwErrnoException(env, "statvfs");
         return NULL;
     }
-    return makeStructStatFs(env, sb);
+    return makeStructStatVfs(env, sb);
 }
 
 static jstring Posix_strerror(JNIEnv* env, jobject, jint errnum) {
@@ -1384,7 +1383,7 @@
     NATIVE_METHOD(Posix, fcntlFlock, "(Ljava/io/FileDescriptor;ILlibcore/io/StructFlock;)I"),
     NATIVE_METHOD(Posix, fdatasync, "(Ljava/io/FileDescriptor;)V"),
     NATIVE_METHOD(Posix, fstat, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStat;"),
-    NATIVE_METHOD(Posix, fstatfs, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStatFs;"),
+    NATIVE_METHOD(Posix, fstatvfs, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStatVfs;"),
     NATIVE_METHOD(Posix, fsync, "(Ljava/io/FileDescriptor;)V"),
     NATIVE_METHOD(Posix, ftruncate, "(Ljava/io/FileDescriptor;J)V"),
     NATIVE_METHOD(Posix, gai_strerror, "(I)Ljava/lang/String;"),
@@ -1406,6 +1405,7 @@
     NATIVE_METHOD(Posix, getsockoptLinger, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructLinger;"),
     NATIVE_METHOD(Posix, getsockoptTimeval, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructTimeval;"),
     NATIVE_METHOD(Posix, getsockoptUcred, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructUcred;"),
+    NATIVE_METHOD(Posix, gettid, "()I"),
     NATIVE_METHOD(Posix, getuid, "()I"),
     NATIVE_METHOD(Posix, if_indextoname, "(I)Ljava/lang/String;"),
     NATIVE_METHOD(Posix, inet_pton, "(ILjava/lang/String;)Ljava/net/InetAddress;"),
@@ -1453,7 +1453,7 @@
     NATIVE_METHOD(Posix, socket, "(III)Ljava/io/FileDescriptor;"),
     NATIVE_METHOD(Posix, socketpair, "(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V"),
     NATIVE_METHOD(Posix, stat, "(Ljava/lang/String;)Llibcore/io/StructStat;"),
-    NATIVE_METHOD(Posix, statfs, "(Ljava/lang/String;)Llibcore/io/StructStatFs;"),
+    NATIVE_METHOD(Posix, statvfs, "(Ljava/lang/String;)Llibcore/io/StructStatVfs;"),
     NATIVE_METHOD(Posix, strerror, "(I)Ljava/lang/String;"),
     NATIVE_METHOD(Posix, strsignal, "(I)Ljava/lang/String;"),
     NATIVE_METHOD(Posix, symlink, "(Ljava/lang/String;Ljava/lang/String;)V"),
diff --git a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index 9b4bb4d..6ba055a 100644
--- a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -332,6 +332,7 @@
     memcpy(newBucket, existingBucket, size * sizeof(InternedString*));
     newBucket[size] = entry;
     newBucket[size + 1] = NULL;
+    delete[] existingBucket;
 
     return newBucket;
 }
@@ -385,6 +386,7 @@
         // Expand the bucket.
         bucket = expandInternedStringBucket(bucket, internedString);
         if (bucket == NULL) {
+            delete internedString;
             jniThrowOutOfMemoryError(env, NULL);
             return NULL;
         }
@@ -400,6 +402,7 @@
         // Create a new bucket with one entry.
         bucket = newInternedStringBucket(internedString);
         if (bucket == NULL) {
+            delete internedString;
             jniThrowOutOfMemoryError(env, NULL);
             return NULL;
         }
diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk
index 7ea5033..e576d1a 100644
--- a/luni/src/main/native/sub.mk
+++ b/luni/src/main/native/sub.mk
@@ -5,8 +5,8 @@
 
 LOCAL_SRC_FILES := \
 	AsynchronousSocketCloseMonitor.cpp \
+	ExecStrings.cpp \
 	IcuUtilities.cpp \
-	JniConstants.cpp \
 	JniException.cpp \
 	NetworkUtilities.cpp \
 	Register.cpp \
@@ -15,6 +15,8 @@
 	java_io_File.cpp \
 	java_io_ObjectStreamClass.cpp \
 	java_lang_Character.cpp \
+	java_lang_Double.cpp \
+	java_lang_Float.cpp \
 	java_lang_Math.cpp \
 	java_lang_ProcessManager.cpp \
 	java_lang_RealToString.cpp \
@@ -32,6 +34,7 @@
 	java_util_zip_Deflater.cpp \
 	java_util_zip_Inflater.cpp \
 	libcore_icu_AlphabeticIndex.cpp \
+	libcore_icu_DateIntervalFormat.cpp \
 	libcore_icu_ICU.cpp \
 	libcore_icu_NativeBreakIterator.cpp \
 	libcore_icu_NativeCollation.cpp \
@@ -48,11 +51,9 @@
 	libcore_io_Posix.cpp \
 	libcore_net_RawSocket.cpp \
 	org_apache_harmony_xml_ExpatParser.cpp \
-	org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp \
 	readlink.cpp \
 	realpath.cpp \
 	sun_misc_Unsafe.cpp \
-	toStringArray.cpp \
 	valueOf.cpp
 
 LOCAL_C_INCLUDES += \
diff --git a/luni/src/main/native/toStringArray.cpp b/luni/src/main/native/toStringArray.cpp
deleted file mode 100644
index 9640d22..0000000
--- a/luni/src/main/native/toStringArray.cpp
+++ /dev/null
@@ -1,102 +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.
- */
-
-#include "JniConstants.h"
-#include "toStringArray.h"
-
-#include <string>
-#include <vector>
-
-struct VectorCounter {
-    const std::vector<std::string>& strings;
-    VectorCounter(const std::vector<std::string>& strings) : strings(strings) {}
-    size_t operator()() {
-        return strings.size();
-    }
-};
-struct VectorGetter {
-    const std::vector<std::string>& strings;
-    VectorGetter(const std::vector<std::string>& strings) : strings(strings) {}
-    const char* operator()(size_t i) {
-        return strings[i].c_str();
-    }
-};
-
-jobjectArray toStringArray(JNIEnv* env, const std::vector<std::string>& strings) {
-    VectorCounter counter(strings);
-    VectorGetter getter(strings);
-    return toStringArray<VectorCounter, VectorGetter>(env, &counter, &getter);
-}
-
-struct ArrayCounter {
-    const char* const* strings;
-    ArrayCounter(const char* const* strings) : strings(strings) {}
-    size_t operator()() {
-        size_t count = 0;
-        while (strings[count] != NULL) {
-            ++count;
-        }
-        return count;
-    }
-};
-
-struct ArrayGetter {
-    const char* const* strings;
-    ArrayGetter(const char* const* strings) : strings(strings) {}
-    const char* operator()(size_t i) {
-        return strings[i];
-    }
-};
-
-jobjectArray toStringArray(JNIEnv* env, const char* const* strings) {
-    ArrayCounter counter(strings);
-    ArrayGetter getter(strings);
-    return toStringArray(env, &counter, &getter);
-}
-
-/** Converts a Java String[] to a 0-terminated char**. */
-char** convertStrings(JNIEnv* env, jobjectArray javaArray) {
-    if (javaArray == NULL) {
-        return NULL;
-    }
-
-    jsize length = env->GetArrayLength(javaArray);
-    char** array = new char*[length + 1];
-    array[length] = 0;
-    for (jsize i = 0; i < length; ++i) {
-        ScopedLocalRef<jstring> javaEntry(env, reinterpret_cast<jstring>(env->GetObjectArrayElement(javaArray, i)));
-        // We need to pass these strings to const-unfriendly code.
-        char* entry = const_cast<char*>(env->GetStringUTFChars(javaEntry.get(), NULL));
-        array[i] = entry;
-    }
-
-    return array;
-}
-
-/** Frees a char** which was converted from a Java String[]. */
-void freeStrings(JNIEnv* env, jobjectArray javaArray, char** array) {
-    if (javaArray == NULL) {
-        return;
-    }
-
-    jsize length = env->GetArrayLength(javaArray);
-    for (jsize i = 0; i < length; ++i) {
-        ScopedLocalRef<jstring> javaEntry(env, reinterpret_cast<jstring>(env->GetObjectArrayElement(javaArray, i)));
-        env->ReleaseStringUTFChars(javaEntry.get(), array[i]);
-    }
-
-    delete[] array;
-}
diff --git a/luni/src/main/native/toStringArray.h b/luni/src/main/native/toStringArray.h
deleted file mode 100644
index c65b8ad..0000000
--- a/luni/src/main/native/toStringArray.h
+++ /dev/null
@@ -1,69 +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.
- */
-
-#include "jni.h"
-#include "ScopedLocalRef.h"
-
-#include <string>
-#include <vector>
-
-template <typename Counter, typename Getter>
-jobjectArray toStringArray(JNIEnv* env, Counter* counter, Getter* getter) {
-    size_t count = (*counter)();
-    jobjectArray result = env->NewObjectArray(count, JniConstants::stringClass, NULL);
-    if (result == NULL) {
-        return NULL;
-    }
-    for (size_t i = 0; i < count; ++i) {
-        ScopedLocalRef<jstring> s(env, env->NewStringUTF((*getter)(i)));
-        if (env->ExceptionCheck()) {
-            return NULL;
-        }
-        env->SetObjectArrayElement(result, i, s.get());
-        if (env->ExceptionCheck()) {
-            return NULL;
-        }
-    }
-    return result;
-}
-
-template <typename Counter, typename Getter>
-jobjectArray toStringArray16(JNIEnv* env, Counter* counter, Getter* getter) {
-    size_t count = (*counter)();
-    jobjectArray result = env->NewObjectArray(count, JniConstants::stringClass, NULL);
-    if (result == NULL) {
-        return NULL;
-    }
-    for (size_t i = 0; i < count; ++i) {
-        int32_t charCount;
-        const jchar* chars = (*getter)(&charCount);
-        ScopedLocalRef<jstring> s(env, env->NewString(chars, charCount));
-        if (env->ExceptionCheck()) {
-            return NULL;
-        }
-        env->SetObjectArrayElement(result, i, s.get());
-        if (env->ExceptionCheck()) {
-            return NULL;
-        }
-    }
-    return result;
-}
-
-jobjectArray toStringArray(JNIEnv* env, const std::vector<std::string>& strings);
-jobjectArray toStringArray(JNIEnv* env, const char* const* strings);
-
-char** convertStrings(JNIEnv* env, jobjectArray javaArray);
-void freeStrings(JNIEnv* env, jobjectArray javaArray, char** array);
diff --git a/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
new file mode 100644
index 0000000..8de3407
--- /dev/null
+++ b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+package libcore.icu;
+
+import java.util.Arrays;
+import java.util.Locale;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+import static libcore.icu.DateIntervalFormat.*;
+
+public class DateIntervalFormatTest extends junit.framework.TestCase {
+  private static final long MINUTE_DURATION = 60 * 1000;
+  private static final long HOUR_DURATION = 60 * MINUTE_DURATION;
+  private static final long DAY_DURATION = 24 * HOUR_DURATION;
+  private static final long MONTH_DURATION = 31 * DAY_DURATION;
+  private static final long YEAR_DURATION = 12 * MONTH_DURATION;
+
+  public void test_formatDateInterval() throws Exception {
+    Date date = new Date(109, 0, 19, 3, 30, 15);
+    long fixedTime = date.getTime();
+
+    int currentYear = Calendar.getInstance().get(Calendar.YEAR);
+    Date dateWithCurrentYear = new Date(currentYear - 1900, 0, 19, 3, 30, 15);
+    long timeWithCurrentYear = dateWithCurrentYear.getTime();
+
+    long noonDuration = (8 * 60 + 30) * 60 * 1000 - 15 * 1000;
+    long midnightDuration = (3 * 60 + 30) * 60 * 1000 + 15 * 1000;
+    long integralDuration = 30 * 60 * 1000 + 15 * 1000;
+
+    // These are the old CTS tests for DateIntervalFormat.formatDateRange.
+
+    Locale de_DE = new Locale("de", "DE");
+    Locale en_US = new Locale("en", "US");
+    Locale es_ES = new Locale("es", "ES");
+    Locale es_US = new Locale("es", "US");
+
+    TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
+
+    assertEquals("Monday", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_WEEKDAY));
+    assertEquals("January 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR_DURATION, FORMAT_SHOW_DATE));
+    assertEquals("3:30 AM", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_SHOW_TIME));
+    assertEquals("January 19, 2009", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_YEAR));
+    assertEquals("January 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR_DURATION, 0 /*FORMAT_NO_YEAR*/));
+    assertEquals("January", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR_DURATION, FORMAT_NO_MONTH_DAY));
+    assertEquals("3:30 AM", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_12HOUR | FORMAT_SHOW_TIME));
+    assertEquals("03:30", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_24HOUR | FORMAT_SHOW_TIME));
+    assertEquals("3:30 AM", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_12HOUR /*| FORMAT_CAP_AMPM*/ | FORMAT_SHOW_TIME));
+    assertEquals("12:00 PM", formatDateRange(en_US, tz, fixedTime + noonDuration, fixedTime + noonDuration, FORMAT_12HOUR | FORMAT_SHOW_TIME));
+    assertEquals("12:00 PM", formatDateRange(en_US, tz, fixedTime + noonDuration, fixedTime + noonDuration, FORMAT_12HOUR | FORMAT_SHOW_TIME /*| FORMAT_CAP_NOON*/));
+    assertEquals("12:00 PM", formatDateRange(en_US, tz, fixedTime + noonDuration, fixedTime + noonDuration, FORMAT_12HOUR /*| FORMAT_NO_NOON*/ | FORMAT_SHOW_TIME));
+    assertEquals("12:00 AM", formatDateRange(en_US, tz, fixedTime - midnightDuration, fixedTime - midnightDuration, FORMAT_12HOUR | FORMAT_SHOW_TIME /*| FORMAT_NO_MIDNIGHT*/));
+    assertEquals("3:30 AM", formatDateRange(en_US, tz, fixedTime, fixedTime, FORMAT_SHOW_TIME | FORMAT_UTC));
+    assertEquals("3 AM", formatDateRange(en_US, tz, fixedTime - integralDuration, fixedTime - integralDuration, FORMAT_SHOW_TIME | FORMAT_ABBREV_TIME));
+    assertEquals("Mon", formatDateRange(en_US, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_WEEKDAY));
+    assertEquals("Jan 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH));
+    assertEquals("Jan 19", formatDateRange(en_US, tz, timeWithCurrentYear, timeWithCurrentYear + HOUR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+
+    assertEquals("1/19/2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * HOUR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("1/19/2009 – 1/22/2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("1/19/2009 – 4/22/2009", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("1/19/2009 – 2/9/2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+
+    assertEquals("19.1.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19.01.2009 - 22.01.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19.01.2009 - 22.04.2009", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19.01.2009 - 09.02.2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+
+    assertEquals("1/19/2009", formatDateRange(es_US, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19/1/2009 – 22/1/2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19/1/2009 – 22/4/2009", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19/1/2009 – 9/2/2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+
+    assertEquals("19/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + HOUR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19/1/2009 – 22/1/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19/1/2009 – 22/4/2009", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+    assertEquals("19/1/2009 – 9/2/2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_YEAR | FORMAT_NUMERIC_DATE));
+
+    // These are some random other test cases I came up with.
+
+    assertEquals("January 19–22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, 0));
+    assertEquals("Jan 19–22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("Mon, Jan 19 – Thu, Jan 22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+    assertEquals("Monday, January 19 – Thursday, January 22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY));
+
+    assertEquals("January 19 – April 22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, 0));
+    assertEquals("Jan 19 – Apr 22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("Mon, Jan 19 – Wed, Apr 22", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+    assertEquals("January–April", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_NO_MONTH_DAY));
+
+    assertEquals("Jan 19, 2009 – Feb 9, 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("Jan 2009 – Feb 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
+    assertEquals("January 19, 2009 – February 9, 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, 0));
+    assertEquals("Monday, January 19, 2009 – Thursday, February 9, 2012", formatDateRange(en_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_WEEKDAY));
+
+    // The same tests but for de_DE.
+
+    assertEquals("19.-22. Januar", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY_DURATION, 0));
+    assertEquals("19.-22. Jan.", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("Mo., 19. - Do., 22. Jan.", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+    assertEquals("Montag, 19. - Donnerstag, 22. Januar", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY));
+
+    assertEquals("19. Januar - 22. April", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, 0));
+    assertEquals("19. Jan. - 22. Apr.", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("Mo., 19. Jan. - Mi., 22. Apr.", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+    assertEquals("Januar-April", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_NO_MONTH_DAY));
+
+    assertEquals("19. Jan. 2009 - 9. Feb. 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("Jan. 2009 - Feb. 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
+    assertEquals("19. Januar 2009 - 9. Februar 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, 0));
+    assertEquals("Montag, 19. Januar 2009 - Donnerstag, 9. Februar 2012", formatDateRange(de_DE, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_WEEKDAY));
+
+    // The same tests but for es_US.
+
+    assertEquals("19–22 enero", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, 0));
+    assertEquals("19–22 ene", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("lun 19 ene – jue 22 ene", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+    assertEquals("lunes 19 enero – jueves 22 enero", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY));
+
+    assertEquals("19 enero – 22 abril", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, 0));
+    assertEquals("19 ene – 22 abr", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("lun 19 ene – mié 22 abr", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+    assertEquals("enero–abril", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_NO_MONTH_DAY));
+
+    assertEquals("19 ene 2009 – 9 feb 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("ene 2009 – feb 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
+    assertEquals("19 enero 2009 – 9 febrero 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, 0));
+    assertEquals("lunes 19 enero 2009 – jueves 9 febrero 2012", formatDateRange(es_US, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_WEEKDAY));
+
+    // The same tests but for es_ES.
+
+    assertEquals("19–22 enero", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY_DURATION, 0));
+    assertEquals("19–22 ene", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("lun 19 ene – jue 22 ene", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+    assertEquals("lunes 19 enero – jueves 22 enero", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * DAY_DURATION, FORMAT_SHOW_WEEKDAY));
+
+    assertEquals("19 enero – 22 abril", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, 0));
+    assertEquals("19 ene – 22 abr", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("lun 19 ene – mié 22 abr", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_SHOW_WEEKDAY | FORMAT_ABBREV_ALL));
+    assertEquals("enero–abril", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * MONTH_DURATION, FORMAT_NO_MONTH_DAY));
+
+    assertEquals("19 ene 2009 – 9 feb 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+    assertEquals("ene 2009 – feb 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_NO_MONTH_DAY | FORMAT_ABBREV_ALL));
+    assertEquals("19 enero 2009 – 9 febrero 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, 0));
+    assertEquals("lunes 19 enero 2009 – jueves 9 febrero 2012", formatDateRange(es_ES, tz, fixedTime, fixedTime + 3 * YEAR_DURATION, FORMAT_SHOW_WEEKDAY));
+  }
+
+  public void test8862241() throws Exception {
+    // Test the post-2038 future (http://b/8862241).
+    TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
+    long jan_19_2042 = new Date(2042 - 1900, 0, 19, 3, 30, 15).getTime();
+    long oct_4_2046 = new Date(2046 - 1900, 9, 4, 3, 30, 15).getTime();
+    assertEquals("Jan 19, 2042 – Oct 4, 2046", formatDateRange(Locale.US, tz, jan_19_2042, oct_4_2046, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL));
+  }
+
+  public void test10089890() throws Exception {
+    // Test that we actually take the time zone into account.
+    // The Unix epoch is UTC, so 0 is 1970-01-01T00:00Z...
+    assertEquals("Jan 1–2", formatDateRange(0, 24*60*60 * 1000L, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL, "Europe/London"));
+    // But MTV is hours behind, so 0 was still the afternoon of the previous day...
+    assertEquals("Dec 31, 1969 – Jan 1, 1970", formatDateRange(0, 24*60*60 * 1000L, FORMAT_SHOW_DATE | FORMAT_ABBREV_ALL, "America/Los_Angeles"));
+  }
+}
diff --git a/luni/src/test/java/libcore/icu/ICUTest.java b/luni/src/test/java/libcore/icu/ICUTest.java
index 9d9892c..b3d16f9 100644
--- a/luni/src/test/java/libcore/icu/ICUTest.java
+++ b/luni/src/test/java/libcore/icu/ICUTest.java
@@ -16,58 +16,111 @@
 
 package libcore.icu;
 
+import java.util.Arrays;
 import java.util.Locale;
 
 public class ICUTest extends junit.framework.TestCase {
-    public void test_getISOLanguages() throws Exception {
-        // Check that corrupting our array doesn't affect other callers.
-        assertNotNull(ICU.getISOLanguages()[0]);
-        ICU.getISOLanguages()[0] = null;
-        assertNotNull(ICU.getISOLanguages()[0]);
+  public void test_getISOLanguages() throws Exception {
+    // Check that corrupting our array doesn't affect other callers.
+    assertNotNull(ICU.getISOLanguages()[0]);
+    ICU.getISOLanguages()[0] = null;
+    assertNotNull(ICU.getISOLanguages()[0]);
+  }
+
+  public void test_getISOCountries() throws Exception {
+    // Check that corrupting our array doesn't affect other callers.
+    assertNotNull(ICU.getISOCountries()[0]);
+    ICU.getISOCountries()[0] = null;
+    assertNotNull(ICU.getISOCountries()[0]);
+  }
+
+  public void test_getAvailableLocales() throws Exception {
+    // Check that corrupting our array doesn't affect other callers.
+    assertNotNull(ICU.getAvailableLocales()[0]);
+    ICU.getAvailableLocales()[0] = null;
+    assertNotNull(ICU.getAvailableLocales()[0]);
+  }
+
+  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"));
+  }
+
+  public void test_localeFromString() throws Exception {
+    // localeFromString is pretty lenient. Some of these can't be round-tripped
+    // through Locale.toString.
+    assertEquals(Locale.ENGLISH, ICU.localeFromString("en"));
+    assertEquals(Locale.ENGLISH, ICU.localeFromString("en_"));
+    assertEquals(Locale.ENGLISH, ICU.localeFromString("en__"));
+    assertEquals(Locale.US, ICU.localeFromString("en_US"));
+    assertEquals(Locale.US, ICU.localeFromString("en_US_"));
+    assertEquals(new Locale("", "US", ""), ICU.localeFromString("_US"));
+    assertEquals(new Locale("", "US", ""), ICU.localeFromString("_US_"));
+    assertEquals(new Locale("", "", "POSIX"), ICU.localeFromString("__POSIX"));
+    assertEquals(new Locale("aa", "BB", "CC"), ICU.localeFromString("aa_BB_CC"));
+  }
+
+  public void test_getScript_addLikelySubtags() throws Exception {
+    assertEquals("Latn", ICU.getScript(ICU.addLikelySubtags("en_US")));
+    assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("he")));
+    assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("he_IL")));
+    assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("iw")));
+    assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("iw_IL")));
+  }
+
+  private String best(Locale l, String skeleton) {
+    return ICU.getBestDateTimePattern(skeleton, l.toString());
+  }
+
+  public void test_getDateFormatOrder() throws Exception {
+    // lv and fa use differing orders depending on whether you're using numeric or textual months.
+    Locale lv = new Locale("lv");
+    assertEquals("[d, M, y]", Arrays.toString(ICU.getDateFormatOrder(best(lv, "yyyy-M-dd"))));
+    assertEquals("[y, d, M]", Arrays.toString(ICU.getDateFormatOrder(best(lv, "yyyy-MMM-dd"))));
+    assertEquals("[d, M, \u0000]", Arrays.toString(ICU.getDateFormatOrder(best(lv, "MMM-dd"))));
+    Locale fa = new Locale("fa");
+    assertEquals("[y, M, d]", Arrays.toString(ICU.getDateFormatOrder(best(fa, "yyyy-M-dd"))));
+    assertEquals("[d, M, y]", Arrays.toString(ICU.getDateFormatOrder(best(fa, "yyyy-MMM-dd"))));
+    assertEquals("[d, M, \u0000]", Arrays.toString(ICU.getDateFormatOrder(best(fa, "MMM-dd"))));
+
+    // English differs on each side of the Atlantic.
+    Locale en_US = Locale.US;
+    assertEquals("[M, d, y]", Arrays.toString(ICU.getDateFormatOrder(best(en_US, "yyyy-M-dd"))));
+    assertEquals("[M, d, y]", Arrays.toString(ICU.getDateFormatOrder(best(en_US, "yyyy-MMM-dd"))));
+    assertEquals("[M, d, \u0000]", Arrays.toString(ICU.getDateFormatOrder(best(en_US, "MMM-dd"))));
+    Locale en_GB = Locale.UK;
+    assertEquals("[d, M, y]", Arrays.toString(ICU.getDateFormatOrder(best(en_GB, "yyyy-M-dd"))));
+    assertEquals("[d, M, y]", Arrays.toString(ICU.getDateFormatOrder(best(en_GB, "yyyy-MMM-dd"))));
+    assertEquals("[d, M, \u0000]", Arrays.toString(ICU.getDateFormatOrder(best(en_GB, "MMM-dd"))));
+
+    assertEquals("[y, M, d]", Arrays.toString(ICU.getDateFormatOrder("yyyy - 'why' '' 'ddd' MMM-dd")));
+
+    try {
+      ICU.getDateFormatOrder("the quick brown fox jumped over the lazy dog");
+      fail();
+    } catch (IllegalArgumentException expected) {
     }
 
-    public void test_getISOCountries() throws Exception {
-        // Check that corrupting our array doesn't affect other callers.
-        assertNotNull(ICU.getISOCountries()[0]);
-        ICU.getISOCountries()[0] = null;
-        assertNotNull(ICU.getISOCountries()[0]);
+    try {
+      ICU.getDateFormatOrder("'");
+      fail();
+    } catch (IllegalArgumentException expected) {
     }
 
-    public void test_getAvailableLocales() throws Exception {
-        // Check that corrupting our array doesn't affect other callers.
-        assertNotNull(ICU.getAvailableLocales()[0]);
-        ICU.getAvailableLocales()[0] = null;
-        assertNotNull(ICU.getAvailableLocales()[0]);
+    try {
+      ICU.getDateFormatOrder("yyyy'");
+      fail();
+    } catch (IllegalArgumentException expected) {
     }
 
-    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"));
+    try {
+      ICU.getDateFormatOrder("yyyy'MMM");
+      fail();
+    } catch (IllegalArgumentException expected) {
     }
-
-    public void test_localeFromString() throws Exception {
-        // localeFromString is pretty lenient. Some of these can't be round-tripped
-        // through Locale.toString.
-        assertEquals(Locale.ENGLISH, ICU.localeFromString("en"));
-        assertEquals(Locale.ENGLISH, ICU.localeFromString("en_"));
-        assertEquals(Locale.ENGLISH, ICU.localeFromString("en__"));
-        assertEquals(Locale.US, ICU.localeFromString("en_US"));
-        assertEquals(Locale.US, ICU.localeFromString("en_US_"));
-        assertEquals(new Locale("", "US", ""), ICU.localeFromString("_US"));
-        assertEquals(new Locale("", "US", ""), ICU.localeFromString("_US_"));
-        assertEquals(new Locale("", "", "POSIX"), ICU.localeFromString("__POSIX"));
-        assertEquals(new Locale("aa", "BB", "CC"), ICU.localeFromString("aa_BB_CC"));
-    }
-
-    public void test_getScript_addLikelySubtags() throws Exception {
-        assertEquals("Latn", ICU.getScript(ICU.addLikelySubtags("en_US")));
-        assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("he")));
-        assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("he_IL")));
-        assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("iw")));
-        assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("iw_IL")));
-    }
+  }
 }
diff --git a/luni/src/test/java/libcore/icu/TransliteratorTest.java b/luni/src/test/java/libcore/icu/TransliteratorTest.java
index e4f7981..9ced2de 100644
--- a/luni/src/test/java/libcore/icu/TransliteratorTest.java
+++ b/luni/src/test/java/libcore/icu/TransliteratorTest.java
@@ -90,7 +90,7 @@
     t = new Transliterator("Han-Latin/Names");
     assertEquals("shěn", t.transliterate("\u6c88"));
     assertEquals("shěn", t.transliterate("\u700b"));
-    assertEquals("jǐa", t.transliterate("\u8d3e"));
+    assertEquals("jiǎ", t.transliterate("\u8d3e"));
 
     t = new Transliterator("Han-Latin/Names; Latin-Ascii; Any-Upper");
     assertEquals("SHEN", t.transliterate("\u6c88"));
diff --git a/luni/src/test/java/libcore/io/DiskLruCacheTest.java b/luni/src/test/java/libcore/io/DiskLruCacheTest.java
deleted file mode 100644
index 7a5bfa5..0000000
--- a/luni/src/test/java/libcore/io/DiskLruCacheTest.java
+++ /dev/null
@@ -1,868 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.io;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import junit.framework.TestCase;
-import static libcore.io.DiskLruCache.JOURNAL_FILE;
-import static libcore.io.DiskLruCache.MAGIC;
-import static libcore.io.DiskLruCache.VERSION_1;
-import tests.io.MockOs;
-
-public final class DiskLruCacheTest extends TestCase {
-    private final int appVersion = 100;
-    private String javaTmpDir;
-    private File cacheDir;
-    private File journalFile;
-    private DiskLruCache cache;
-    private final MockOs mockOs = new MockOs();
-
-    @Override public void setUp() throws Exception {
-        super.setUp();
-        javaTmpDir = System.getProperty("java.io.tmpdir");
-        cacheDir = new File(javaTmpDir, "DiskLruCacheTest");
-        cacheDir.mkdir();
-        journalFile = new File(cacheDir, JOURNAL_FILE);
-        for (File file : cacheDir.listFiles()) {
-            file.delete();
-        }
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        mockOs.install();
-    }
-
-    @Override protected void tearDown() throws Exception {
-        mockOs.uninstall();
-        cache.close();
-        super.tearDown();
-    }
-
-    public void testEmptyCache() throws Exception {
-        cache.close();
-        assertJournalEquals();
-    }
-
-    public void testWriteAndReadEntry() throws Exception {
-        DiskLruCache.Editor creator = cache.edit("k1");
-        creator.set(0, "ABC");
-        creator.set(1, "DE");
-        assertNull(creator.getString(0));
-        assertNull(creator.newInputStream(0));
-        assertNull(creator.getString(1));
-        assertNull(creator.newInputStream(1));
-        creator.commit();
-
-        DiskLruCache.Snapshot snapshot = cache.get("k1");
-        assertEquals("ABC", snapshot.getString(0));
-        assertEquals("DE", snapshot.getString(1));
-    }
-
-    public void testReadAndWriteEntryAcrossCacheOpenAndClose() throws Exception {
-        DiskLruCache.Editor creator = cache.edit("k1");
-        creator.set(0, "A");
-        creator.set(1, "B");
-        creator.commit();
-        cache.close();
-
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        DiskLruCache.Snapshot snapshot = cache.get("k1");
-        assertEquals("A", snapshot.getString(0));
-        assertEquals("B", snapshot.getString(1));
-        snapshot.close();
-    }
-
-    public void testJournalWithEditAndPublish() throws Exception {
-        DiskLruCache.Editor creator = cache.edit("k1");
-        assertJournalEquals("DIRTY k1"); // DIRTY must always be flushed
-        creator.set(0, "AB");
-        creator.set(1, "C");
-        creator.commit();
-        cache.close();
-        assertJournalEquals("DIRTY k1", "CLEAN k1 2 1");
-    }
-
-    public void testRevertedNewFileIsRemoveInJournal() throws Exception {
-        DiskLruCache.Editor creator = cache.edit("k1");
-        assertJournalEquals("DIRTY k1"); // DIRTY must always be flushed
-        creator.set(0, "AB");
-        creator.set(1, "C");
-        creator.abort();
-        cache.close();
-        assertJournalEquals("DIRTY k1", "REMOVE k1");
-    }
-
-    public void testUnterminatedEditIsRevertedOnClose() throws Exception {
-        cache.edit("k1");
-        cache.close();
-        assertJournalEquals("DIRTY k1", "REMOVE k1");
-    }
-
-    public void testJournalDoesNotIncludeReadOfYetUnpublishedValue() throws Exception {
-        DiskLruCache.Editor creator = cache.edit("k1");
-        assertNull(cache.get("k1"));
-        creator.set(0, "A");
-        creator.set(1, "BC");
-        creator.commit();
-        cache.close();
-        assertJournalEquals("DIRTY k1", "CLEAN k1 1 2");
-    }
-
-    public void testJournalWithEditAndPublishAndRead() throws Exception {
-        DiskLruCache.Editor k1Creator = cache.edit("k1");
-        k1Creator.set(0, "AB");
-        k1Creator.set(1, "C");
-        k1Creator.commit();
-        DiskLruCache.Editor k2Creator = cache.edit("k2");
-        k2Creator.set(0, "DEF");
-        k2Creator.set(1, "G");
-        k2Creator.commit();
-        DiskLruCache.Snapshot k1Snapshot = cache.get("k1");
-        k1Snapshot.close();
-        cache.close();
-        assertJournalEquals("DIRTY k1", "CLEAN k1 2 1",
-                "DIRTY k2", "CLEAN k2 3 1",
-                "READ k1");
-    }
-
-    public void testCannotOperateOnEditAfterPublish() throws Exception {
-        DiskLruCache.Editor editor = cache.edit("k1");
-        editor.set(0, "A");
-        editor.set(1, "B");
-        editor.commit();
-        assertInoperable(editor);
-    }
-
-    public void testCannotOperateOnEditAfterRevert() throws Exception {
-        DiskLruCache.Editor editor = cache.edit("k1");
-        editor.set(0, "A");
-        editor.set(1, "B");
-        editor.abort();
-        assertInoperable(editor);
-    }
-
-    public void testExplicitRemoveAppliedToDiskImmediately() throws Exception {
-        DiskLruCache.Editor editor = cache.edit("k1");
-        editor.set(0, "ABC");
-        editor.set(1, "B");
-        editor.commit();
-        File k1 = getCleanFile("k1", 0);
-        assertEquals("ABC", readFile(k1));
-        cache.remove("k1");
-        assertFalse(k1.exists());
-    }
-
-    /**
-     * Each read sees a snapshot of the file at the time read was called.
-     * This means that two reads of the same key can see different data.
-     */
-    public void testReadAndWriteOverlapsMaintainConsistency() throws Exception {
-        DiskLruCache.Editor v1Creator = cache.edit("k1");
-        v1Creator.set(0, "AAaa");
-        v1Creator.set(1, "BBbb");
-        v1Creator.commit();
-
-        DiskLruCache.Snapshot snapshot1 = cache.get("k1");
-        InputStream inV1 = snapshot1.getInputStream(0);
-        assertEquals('A', inV1.read());
-        assertEquals('A', inV1.read());
-
-        DiskLruCache.Editor v1Updater = cache.edit("k1");
-        v1Updater.set(0, "CCcc");
-        v1Updater.set(1, "DDdd");
-        v1Updater.commit();
-
-        DiskLruCache.Snapshot snapshot2 = cache.get("k1");
-        assertEquals("CCcc", snapshot2.getString(0));
-        assertEquals("DDdd", snapshot2.getString(1));
-        snapshot2.close();
-
-        assertEquals('a', inV1.read());
-        assertEquals('a', inV1.read());
-        assertEquals("BBbb", snapshot1.getString(1));
-        snapshot1.close();
-    }
-
-    public void testOpenWithDirtyKeyDeletesAllFilesForThatKey() throws Exception {
-        cache.close();
-        File cleanFile0 = getCleanFile("k1", 0);
-        File cleanFile1 = getCleanFile("k1", 1);
-        File dirtyFile0 = getDirtyFile("k1", 0);
-        File dirtyFile1 = getDirtyFile("k1", 1);
-        writeFile(cleanFile0, "A");
-        writeFile(cleanFile1, "B");
-        writeFile(dirtyFile0, "C");
-        writeFile(dirtyFile1, "D");
-        createJournal("CLEAN k1 1 1", "DIRTY   k1");
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        assertFalse(cleanFile0.exists());
-        assertFalse(cleanFile1.exists());
-        assertFalse(dirtyFile0.exists());
-        assertFalse(dirtyFile1.exists());
-        assertNull(cache.get("k1"));
-    }
-
-    public void testOpenWithInvalidVersionClearsDirectory() throws Exception {
-        cache.close();
-        generateSomeGarbageFiles();
-        createJournalWithHeader(MAGIC, "0", "100", "2", "");
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        assertGarbageFilesAllDeleted();
-    }
-
-    public void testOpenWithInvalidAppVersionClearsDirectory() throws Exception {
-        cache.close();
-        generateSomeGarbageFiles();
-        createJournalWithHeader(MAGIC, "1", "101", "2", "");
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        assertGarbageFilesAllDeleted();
-    }
-
-    public void testOpenWithInvalidValueCountClearsDirectory() throws Exception {
-        cache.close();
-        generateSomeGarbageFiles();
-        createJournalWithHeader(MAGIC, "1", "100", "1", "");
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        assertGarbageFilesAllDeleted();
-    }
-
-    public void testOpenWithInvalidBlankLineClearsDirectory() throws Exception {
-        cache.close();
-        generateSomeGarbageFiles();
-        createJournalWithHeader(MAGIC, "1", "100", "2", "x");
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        assertGarbageFilesAllDeleted();
-    }
-
-    public void testOpenWithInvalidJournalLineClearsDirectory() throws Exception {
-        cache.close();
-        generateSomeGarbageFiles();
-        createJournal("CLEAN k1 1 1", "BOGUS");
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        assertGarbageFilesAllDeleted();
-        assertNull(cache.get("k1"));
-    }
-
-    public void testOpenWithInvalidFileSizeClearsDirectory() throws Exception {
-        cache.close();
-        generateSomeGarbageFiles();
-        createJournal("CLEAN k1 0000x001 1");
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        assertGarbageFilesAllDeleted();
-        assertNull(cache.get("k1"));
-    }
-
-    public void testOpenWithTruncatedLineDiscardsThatLine() throws Exception {
-        cache.close();
-        writeFile(getCleanFile("k1", 0), "A");
-        writeFile(getCleanFile("k1", 1), "B");
-        Writer writer = new FileWriter(journalFile);
-        writer.write(MAGIC + "\n" + VERSION_1 + "\n100\n2\n\nCLEAN k1 1 1"); // no trailing newline
-        writer.close();
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        assertNull(cache.get("k1"));
-    }
-
-    public void testOpenWithTooManyFileSizesClearsDirectory() throws Exception {
-        cache.close();
-        generateSomeGarbageFiles();
-        createJournal("CLEAN k1 1 1 1");
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-        assertGarbageFilesAllDeleted();
-        assertNull(cache.get("k1"));
-    }
-
-    public void testKeyWithSpaceNotPermitted() throws Exception {
-        try {
-            cache.edit("my key");
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testKeyWithNewlineNotPermitted() throws Exception {
-        try {
-            cache.edit("my\nkey");
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testKeyWithCarriageReturnNotPermitted() throws Exception {
-        try {
-            cache.edit("my\rkey");
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testNullKeyThrows() throws Exception {
-        try {
-            cache.edit(null);
-            fail();
-        } catch (NullPointerException expected) {
-        }
-    }
-
-    public void testCreateNewEntryWithTooFewValuesFails() throws Exception {
-        DiskLruCache.Editor creator = cache.edit("k1");
-        creator.set(1, "A");
-        try {
-            creator.commit();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-
-        assertFalse(getCleanFile("k1", 0).exists());
-        assertFalse(getCleanFile("k1", 1).exists());
-        assertFalse(getDirtyFile("k1", 0).exists());
-        assertFalse(getDirtyFile("k1", 1).exists());
-        assertNull(cache.get("k1"));
-
-        DiskLruCache.Editor creator2 = cache.edit("k1");
-        creator2.set(0, "B");
-        creator2.set(1, "C");
-        creator2.commit();
-    }
-
-    public void testCreateNewEntryWithMissingFileAborts() throws Exception {
-        DiskLruCache.Editor creator = cache.edit("k1");
-        creator.set(0, "A");
-        creator.set(1, "A");
-        assertTrue(getDirtyFile("k1", 0).exists());
-        assertTrue(getDirtyFile("k1", 1).exists());
-        assertTrue(getDirtyFile("k1", 0).delete());
-        assertFalse(getDirtyFile("k1", 0).exists());
-        creator.commit();  // silently abort if file does not exist due to I/O issue
-
-        assertFalse(getCleanFile("k1", 0).exists());
-        assertFalse(getCleanFile("k1", 1).exists());
-        assertFalse(getDirtyFile("k1", 0).exists());
-        assertFalse(getDirtyFile("k1", 1).exists());
-        assertNull(cache.get("k1"));
-
-        DiskLruCache.Editor creator2 = cache.edit("k1");
-        creator2.set(0, "B");
-        creator2.set(1, "C");
-        creator2.commit();
-    }
-
-    public void testRevertWithTooFewValues() throws Exception {
-        DiskLruCache.Editor creator = cache.edit("k1");
-        creator.set(1, "A");
-        creator.abort();
-        assertFalse(getCleanFile("k1", 0).exists());
-        assertFalse(getCleanFile("k1", 1).exists());
-        assertFalse(getDirtyFile("k1", 0).exists());
-        assertFalse(getDirtyFile("k1", 1).exists());
-        assertNull(cache.get("k1"));
-    }
-
-    public void testUpdateExistingEntryWithTooFewValuesReusesPreviousValues() throws Exception {
-        DiskLruCache.Editor creator = cache.edit("k1");
-        creator.set(0, "A");
-        creator.set(1, "B");
-        creator.commit();
-
-        DiskLruCache.Editor updater = cache.edit("k1");
-        updater.set(0, "C");
-        updater.commit();
-
-        DiskLruCache.Snapshot snapshot = cache.get("k1");
-        assertEquals("C", snapshot.getString(0));
-        assertEquals("B", snapshot.getString(1));
-        snapshot.close();
-    }
-
-    public void testEvictOnInsert() throws Exception {
-        cache.close();
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-
-        set("A", "a", "aaa"); // size 4
-        set("B", "bb", "bbbb"); // size 6
-        assertEquals(10, cache.size());
-
-        // cause the size to grow to 12 should evict 'A'
-        set("C", "c", "c");
-        cache.flush();
-        assertEquals(8, cache.size());
-        assertAbsent("A");
-        assertValue("B", "bb", "bbbb");
-        assertValue("C", "c", "c");
-
-        // causing the size to grow to 10 should evict nothing
-        set("D", "d", "d");
-        cache.flush();
-        assertEquals(10, cache.size());
-        assertAbsent("A");
-        assertValue("B", "bb", "bbbb");
-        assertValue("C", "c", "c");
-        assertValue("D", "d", "d");
-
-        // causing the size to grow to 18 should evict 'B' and 'C'
-        set("E", "eeee", "eeee");
-        cache.flush();
-        assertEquals(10, cache.size());
-        assertAbsent("A");
-        assertAbsent("B");
-        assertAbsent("C");
-        assertValue("D", "d", "d");
-        assertValue("E", "eeee", "eeee");
-    }
-
-    public void testEvictOnUpdate() throws Exception {
-        cache.close();
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-
-        set("A", "a", "aa"); // size 3
-        set("B", "b", "bb"); // size 3
-        set("C", "c", "cc"); // size 3
-        assertEquals(9, cache.size());
-
-        // causing the size to grow to 11 should evict 'A'
-        set("B", "b", "bbbb");
-        cache.flush();
-        assertEquals(8, cache.size());
-        assertAbsent("A");
-        assertValue("B", "b", "bbbb");
-        assertValue("C", "c", "cc");
-    }
-
-    public void testEvictionHonorsLruFromCurrentSession() throws Exception {
-        cache.close();
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-        set("A", "a", "a");
-        set("B", "b", "b");
-        set("C", "c", "c");
-        set("D", "d", "d");
-        set("E", "e", "e");
-        cache.get("B").close(); // 'B' is now least recently used
-
-        // causing the size to grow to 12 should evict 'A'
-        set("F", "f", "f");
-        // causing the size to grow to 12 should evict 'C'
-        set("G", "g", "g");
-        cache.flush();
-        assertEquals(10, cache.size());
-        assertAbsent("A");
-        assertValue("B", "b", "b");
-        assertAbsent("C");
-        assertValue("D", "d", "d");
-        assertValue("E", "e", "e");
-        assertValue("F", "f", "f");
-    }
-
-    public void testEvictionHonorsLruFromPreviousSession() throws Exception {
-        set("A", "a", "a");
-        set("B", "b", "b");
-        set("C", "c", "c");
-        set("D", "d", "d");
-        set("E", "e", "e");
-        set("F", "f", "f");
-        cache.get("B").close(); // 'B' is now least recently used
-        assertEquals(12, cache.size());
-        cache.close();
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-
-        set("G", "g", "g");
-        cache.flush();
-        assertEquals(10, cache.size());
-        assertAbsent("A");
-        assertValue("B", "b", "b");
-        assertAbsent("C");
-        assertValue("D", "d", "d");
-        assertValue("E", "e", "e");
-        assertValue("F", "f", "f");
-        assertValue("G", "g", "g");
-    }
-
-    public void testCacheSingleEntryOfSizeGreaterThanMaxSize() throws Exception {
-        cache.close();
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-        set("A", "aaaaa", "aaaaaa"); // size=11
-        cache.flush();
-        assertAbsent("A");
-    }
-
-    public void testCacheSingleValueOfSizeGreaterThanMaxSize() throws Exception {
-        cache.close();
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-        set("A", "aaaaaaaaaaa", "a"); // size=12
-        cache.flush();
-        assertAbsent("A");
-    }
-
-    public void testConstructorDoesNotAllowZeroCacheSize() throws Exception {
-        try {
-            DiskLruCache.open(cacheDir, appVersion, 2, 0);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testConstructorDoesNotAllowZeroValuesPerEntry() throws Exception {
-        try {
-            DiskLruCache.open(cacheDir, appVersion, 0, 10);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-    }
-
-    public void testRemoveAbsentElement() throws Exception {
-        cache.remove("A");
-    }
-
-    public void testReadingTheSameStreamMultipleTimes() throws Exception {
-        set("A", "a", "b");
-        DiskLruCache.Snapshot snapshot = cache.get("A");
-        assertSame(snapshot.getInputStream(0), snapshot.getInputStream(0));
-        snapshot.close();
-    }
-
-    public void testRebuildJournalOnRepeatedReads() throws Exception {
-        set("A", "a", "a");
-        set("B", "b", "b");
-        long lastJournalLength = 0;
-        while (true) {
-            long journalLength = journalFile.length();
-            assertValue("A", "a", "a");
-            assertValue("B", "b", "b");
-            if (journalLength < lastJournalLength) {
-                System.out.printf("Journal compacted from %s bytes to %s bytes\n",
-                        lastJournalLength, journalLength);
-                break; // test passed!
-            }
-            lastJournalLength = journalLength;
-        }
-    }
-
-    public void testRebuildJournalOnRepeatedEdits() throws Exception {
-        long lastJournalLength = 0;
-        while (true) {
-            long journalLength = journalFile.length();
-            set("A", "a", "a");
-            set("B", "b", "b");
-            if (journalLength < lastJournalLength) {
-                System.out.printf("Journal compacted from %s bytes to %s bytes\n",
-                        lastJournalLength, journalLength);
-                break;
-            }
-            lastJournalLength = journalLength;
-        }
-
-        // sanity check that a rebuilt journal behaves normally
-        assertValue("A", "a", "a");
-        assertValue("B", "b", "b");
-    }
-
-    /** @see <a href="https://github.com/JakeWharton/DiskLruCache/issues/28">Issue #28</a> */
-    public void testRebuildJournalOnRepeatedReadsWithOpenAndClose() throws Exception {
-        set("a", "a", "a");
-        set("b", "b", "b");
-        long lastJournalLength = 0;
-        while (true) {
-            long journalLength = journalFile.length();
-            assertValue("a", "a", "a");
-            assertValue("b", "b", "b");
-            cache.close();
-            cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-            if (journalLength < lastJournalLength) {
-                System.out.printf("Journal compacted from %s bytes to %s bytes\n",
-                        lastJournalLength, journalLength);
-                break; // test passed!
-            }
-            lastJournalLength = journalLength;
-        }
-    }
-
-    /** @see <a href="https://github.com/JakeWharton/DiskLruCache/issues/28">Issue #28</a> */
-    public void testRebuildJournalOnRepeatedEditsWithOpenAndClose() throws Exception {
-        long lastJournalLength = 0;
-        while (true) {
-            long journalLength = journalFile.length();
-            set("a", "a", "a");
-            set("b", "b", "b");
-            cache.close();
-            cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
-            if (journalLength < lastJournalLength) {
-                System.out.printf("Journal compacted from %s bytes to %s bytes\n",
-                        lastJournalLength, journalLength);
-                break;
-            }
-            lastJournalLength = journalLength;
-        }
-    }
-
-    public void testOpenCreatesDirectoryIfNecessary() throws Exception {
-        cache.close();
-        File dir = new File(javaTmpDir, "testOpenCreatesDirectoryIfNecessary");
-        cache = DiskLruCache.open(dir, appVersion, 2, Integer.MAX_VALUE);
-        set("A", "a", "a");
-        assertTrue(new File(dir, "A.0").exists());
-        assertTrue(new File(dir, "A.1").exists());
-        assertTrue(new File(dir, "journal").exists());
-    }
-
-    public void testFileDeletedExternally() throws Exception {
-        set("A", "a", "a");
-        getCleanFile("A", 1).delete();
-        assertNull(cache.get("A"));
-    }
-
-    public void testFileBecomesInaccessibleDuringReadResultsInIoException() throws Exception {
-        set("A", "aaaaa", "a");
-        DiskLruCache.Snapshot snapshot = cache.get("A");
-        InputStream in = snapshot.getInputStream(0);
-        assertEquals('a', in.read());
-        mockOs.enqueueFault("read");
-        try {
-            in.read();
-            fail();
-        } catch (IOException expected) {
-        }
-        snapshot.close();
-    }
-
-    public void testFileBecomesInaccessibleDuringWriteIsSilentlyDiscarded() throws Exception {
-        set("A", "a", "a");
-        DiskLruCache.Editor editor = cache.edit("A");
-        OutputStream out0 = editor.newOutputStream(0);
-        out0.write('b');
-        out0.close();
-        OutputStream out1 = editor.newOutputStream(1);
-        out1.write('c');
-        mockOs.enqueueFault("write");
-        out1.write('c'); // this doesn't throw...
-        out1.close();
-        editor.commit(); // ... but this will abort
-        assertAbsent("A");
-    }
-
-    public void testEditSameVersion() throws Exception {
-        set("A", "a", "a");
-        DiskLruCache.Snapshot snapshot = cache.get("A");
-        DiskLruCache.Editor editor = snapshot.edit();
-        editor.set(1, "a2");
-        editor.commit();
-        assertValue("A", "a", "a2");
-    }
-
-    public void testEditSnapshotAfterChangeAborted() throws Exception {
-        set("A", "a", "a");
-        DiskLruCache.Snapshot snapshot = cache.get("A");
-        DiskLruCache.Editor toAbort = snapshot.edit();
-        toAbort.set(0, "b");
-        toAbort.abort();
-        DiskLruCache.Editor editor = snapshot.edit();
-        editor.set(1, "a2");
-        editor.commit();
-        assertValue("A", "a", "a2");
-    }
-
-    public void testEditSnapshotAfterChangeCommitted() throws Exception {
-        set("A", "a", "a");
-        DiskLruCache.Snapshot snapshot = cache.get("A");
-        DiskLruCache.Editor toAbort = snapshot.edit();
-        toAbort.set(0, "b");
-        toAbort.commit();
-        assertNull(snapshot.edit());
-    }
-
-    public void testEditSinceEvicted() throws Exception {
-        cache.close();
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-        set("A", "aa", "aaa"); // size 5
-        DiskLruCache.Snapshot snapshot = cache.get("A");
-        set("B", "bb", "bbb"); // size 5
-        set("C", "cc", "ccc"); // size 5; will evict 'A'
-        cache.flush();
-        assertNull(snapshot.edit());
-    }
-
-    public void testEditSinceEvictedAndRecreated() throws Exception {
-        cache.close();
-        cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-        set("A", "aa", "aaa"); // size 5
-        DiskLruCache.Snapshot snapshot = cache.get("A");
-        set("B", "bb", "bbb"); // size 5
-        set("C", "cc", "ccc"); // size 5; will evict 'A'
-        set("A", "a", "aaaa"); // size 5; will evict 'B'
-        cache.flush();
-        assertNull(snapshot.edit());
-    }
-
-    private void assertJournalEquals(String... expectedBodyLines) throws Exception {
-        List<String> expectedLines = new ArrayList<String>();
-        expectedLines.add(MAGIC);
-        expectedLines.add(VERSION_1);
-        expectedLines.add("100");
-        expectedLines.add("2");
-        expectedLines.add("");
-        expectedLines.addAll(Arrays.asList(expectedBodyLines));
-        assertEquals(expectedLines, readJournalLines());
-    }
-
-    private void createJournal(String... bodyLines) throws Exception {
-        createJournalWithHeader(MAGIC, VERSION_1, "100", "2", "", bodyLines);
-    }
-
-    private void createJournalWithHeader(String magic, String version, String appVersion,
-            String valueCount, String blank, String... bodyLines) throws Exception {
-        Writer writer = new FileWriter(journalFile);
-        writer.write(magic + "\n");
-        writer.write(version + "\n");
-        writer.write(appVersion + "\n");
-        writer.write(valueCount + "\n");
-        writer.write(blank + "\n");
-        for (String line : bodyLines) {
-            writer.write(line);
-            writer.write('\n');
-        }
-        writer.close();
-    }
-
-    private List<String> readJournalLines() throws Exception {
-        List<String> result = new ArrayList<String>();
-        BufferedReader reader = new BufferedReader(new FileReader(journalFile));
-        String line;
-        while ((line = reader.readLine()) != null) {
-            result.add(line);
-        }
-        reader.close();
-        return result;
-    }
-
-    private File getCleanFile(String key, int index) {
-        return new File(cacheDir, key + "." + index);
-    }
-
-    private File getDirtyFile(String key, int index) {
-        return new File(cacheDir, key + "." + index + ".tmp");
-    }
-
-    private String readFile(File file) throws Exception {
-        Reader reader = new FileReader(file);
-        StringWriter writer = new StringWriter();
-        char[] buffer = new char[1024];
-        int count;
-        while ((count = reader.read(buffer)) != -1) {
-            writer.write(buffer, 0, count);
-        }
-        reader.close();
-        return writer.toString();
-    }
-
-    public void writeFile(File file, String content) throws Exception {
-        FileWriter writer = new FileWriter(file);
-        writer.write(content);
-        writer.close();
-    }
-
-    private void assertInoperable(DiskLruCache.Editor editor) throws Exception {
-        try {
-            editor.getString(0);
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            editor.set(0, "A");
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            editor.newInputStream(0);
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            editor.newOutputStream(0);
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            editor.commit();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            editor.abort();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-    }
-
-    private void generateSomeGarbageFiles() throws Exception {
-        File dir1 = new File(cacheDir, "dir1");
-        File dir2 = new File(dir1, "dir2");
-        writeFile(getCleanFile("g1", 0), "A");
-        writeFile(getCleanFile("g1", 1), "B");
-        writeFile(getCleanFile("g2", 0), "C");
-        writeFile(getCleanFile("g2", 1), "D");
-        writeFile(getCleanFile("g2", 1), "D");
-        writeFile(new File(cacheDir, "otherFile0"), "E");
-        dir1.mkdir();
-        dir2.mkdir();
-        writeFile(new File(dir2, "otherFile1"), "F");
-    }
-
-    private void assertGarbageFilesAllDeleted() throws Exception {
-        assertFalse(getCleanFile("g1", 0).exists());
-        assertFalse(getCleanFile("g1", 1).exists());
-        assertFalse(getCleanFile("g2", 0).exists());
-        assertFalse(getCleanFile("g2", 1).exists());
-        assertFalse(new File(cacheDir, "otherFile0").exists());
-        assertFalse(new File(cacheDir, "dir1").exists());
-    }
-
-    private void set(String key, String value0, String value1) throws Exception {
-        DiskLruCache.Editor editor = cache.edit(key);
-        editor.set(0, value0);
-        editor.set(1, value1);
-        editor.commit();
-    }
-
-    private void assertAbsent(String key) throws Exception {
-        DiskLruCache.Snapshot snapshot = cache.get(key);
-        if (snapshot != null) {
-            snapshot.close();
-            fail();
-        }
-        assertFalse(getCleanFile(key, 0).exists());
-        assertFalse(getCleanFile(key, 1).exists());
-        assertFalse(getDirtyFile(key, 0).exists());
-        assertFalse(getDirtyFile(key, 1).exists());
-    }
-
-    private void assertValue(String key, String value0, String value1) throws Exception {
-        DiskLruCache.Snapshot snapshot = cache.get(key);
-        assertEquals(value0, snapshot.getString(0));
-        assertEquals(value1, snapshot.getString(1));
-        assertTrue(getCleanFile(key, 0).exists());
-        assertTrue(getCleanFile(key, 1).exists());
-        snapshot.close();
-    }
-}
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index 5e0e8c7..624c119 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -24,6 +24,7 @@
 import java.net.InetUnixAddress;
 import java.net.ServerSocket;
 import java.net.SocketAddress;
+import java.util.Locale;
 import junit.framework.TestCase;
 
 import static libcore.io.OsConstants.*;
@@ -79,7 +80,7 @@
           int requestLength = Libcore.os.read(clientFd, request, 0, request.length);
 
           String s = new String(request, "UTF-8");
-          byte[] response = s.toUpperCase().getBytes("UTF-8");
+          byte[] response = s.toUpperCase(Locale.ROOT).getBytes("UTF-8");
           Libcore.os.write(clientFd, response, 0, response.length);
 
           Libcore.os.close(clientFd);
@@ -103,7 +104,7 @@
     byte[] response = new byte[request.length];
     assertEquals(response.length, Libcore.os.read(clientFd, response, 0, response.length));
 
-    assertEquals(string.toUpperCase(), new String(response, "UTF-8"));
+    assertEquals(string.toUpperCase(Locale.ROOT), new String(response, "UTF-8"));
 
     Libcore.os.close(clientFd);
   }
diff --git a/luni/src/test/java/libcore/io/StrictLineReaderTest.java b/luni/src/test/java/libcore/io/StrictLineReaderTest.java
index d5d3381..db88a6b 100644
--- a/luni/src/test/java/libcore/io/StrictLineReaderTest.java
+++ b/luni/src/test/java/libcore/io/StrictLineReaderTest.java
@@ -23,7 +23,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStream;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 
 public class StrictLineReaderTest extends TestCase {
 
@@ -31,7 +31,7 @@
         try {
             // Testing with LineReader buffer capacity 32 to check some corner cases.
             StrictLineReader lineReader = new StrictLineReader(createTestInputStream(), 32,
-                    Charsets.US_ASCII);
+                                                               StandardCharsets.US_ASCII);
             InputStream refStream = createTestInputStream();
             while (true) {
                 try {
@@ -81,4 +81,3 @@
                 ).getBytes());
     }
 }
-
diff --git a/luni/src/test/java/libcore/java/io/OldAndroidInputStreamReaderTest.java b/luni/src/test/java/libcore/java/io/OldAndroidInputStreamReaderTest.java
index 7a0d5fc..004fe76 100644
--- a/luni/src/test/java/libcore/java/io/OldAndroidInputStreamReaderTest.java
+++ b/luni/src/test/java/libcore/java/io/OldAndroidInputStreamReaderTest.java
@@ -38,7 +38,7 @@
             assertEquals('A', x);
             char[] c = new char[26];
             x = a.read(c, 0, 26);
-            assertTrue(a.getEncoding().equalsIgnoreCase("ISO8859_1"));
+            assertEquals("ISO-8859-1", a.getEncoding());
             assertEquals(26, x);
             assertEquals("bCdEfGhIjKlMnOpQrStUvWxYzX", String.valueOf(c));
         } finally {
@@ -58,7 +58,7 @@
         InputStreamReader a = new InputStreamReader(aa);
 
         try {
-            assertEquals("UTF8", a.getEncoding());
+            assertEquals("UTF-8", a.getEncoding());
 
             int x = a.read();
             assertEquals('A', x);
diff --git a/luni/src/test/java/libcore/java/io/OldAndroidOutputStreamWriterTest.java b/luni/src/test/java/libcore/java/io/OldAndroidOutputStreamWriterTest.java
index de559ff..b4d91e1 100644
--- a/luni/src/test/java/libcore/java/io/OldAndroidOutputStreamWriterTest.java
+++ b/luni/src/test/java/libcore/java/io/OldAndroidOutputStreamWriterTest.java
@@ -35,7 +35,7 @@
             // We have to flush the OutputStreamWriter to guarantee
             // that the results will appear in the underlying OutputStream
             a.flush();
-            assertEquals("ISO8859_1", a.getEncoding());
+            assertEquals("ISO-8859-1", a.getEncoding());
             assertEquals(5, aa.size());
             assertEquals("AbCdA", aa.toString());
         } finally {
diff --git a/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java b/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java
index 214c1b2..986c672 100644
--- a/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java
+++ b/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java
@@ -19,8 +19,13 @@
 
 import java.io.BufferedReader;
 import java.io.CharArrayReader;
+import java.io.InputStreamReader;
 import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
 import java.io.PipedReader;
+import java.io.PrintWriter;
 import java.io.Reader;
 import java.io.StringReader;
 import tests.support.Support_ASimpleReader;
@@ -318,4 +323,79 @@
         } catch (Exception e) {
         }
     }
+
+    public void test_readLine_all_line_endings() throws Exception {
+        BufferedReader r = new BufferedReader(new StringReader("1\r2\n3\r\n4"));
+        assertEquals("1", r.readLine());
+        assertEquals("2", r.readLine());
+        assertEquals("3", r.readLine());
+        assertEquals("4", r.readLine());
+        assertNull(r.readLine());
+    }
+
+    public void test_readLine_interaction_with_read() throws Exception {
+        BufferedReader r = new BufferedReader(new StringReader("1\r\n2"));
+        assertEquals('1', r.read());
+        assertEquals('\r', r.read());
+        assertEquals("", r.readLine()); // The '\r' we read() didn't count.
+        assertEquals("2", r.readLine());
+        assertNull(r.readLine());
+    }
+
+    public void test_readLine_interaction_with_array_read_1() throws Exception {
+        BufferedReader r = new BufferedReader(new StringReader("1\r\n2"));
+        assertEquals(2, r.read(new char[2], 0, 2));
+        assertEquals("", r.readLine()); // The '\r' we read() didn't count.
+        assertEquals("2", r.readLine());
+        assertNull(r.readLine());
+    }
+
+    public void test_readLine_interaction_with_array_read_2() throws Exception {
+        BufferedReader r = new BufferedReader(new StringReader("1\r\n2"));
+        assertEquals("1", r.readLine());
+        char[] chars = new char[1];
+        assertEquals(1, r.read(chars, 0, 1)); // This read skips the '\n'.
+        assertEquals('2', chars[0]);
+        assertNull(r.readLine());
+    }
+
+    public void test_readLine_interaction_with_skip() throws Exception {
+        BufferedReader r = new BufferedReader(new StringReader("1\r\n2"));
+        assertEquals(2, r.skip(2));
+        assertEquals("", r.readLine()); // The '\r' we skip()ed didn't count.
+        assertEquals("2", r.readLine());
+        assertNull(r.readLine());
+    }
+
+    public void test_readLine_interaction_with_mark_and_reset() throws Exception {
+        BufferedReader r = new BufferedReader(new StringReader("1\r\n2\n3"));
+        assertEquals("1", r.readLine());
+        r.mark(256);
+        assertEquals('2', r.read()); // This read skips the '\n'.
+        assertEquals("", r.readLine());
+        r.reset(); // Now we're back half-way through the "\r\n".
+        assertEquals("2", r.readLine());
+        assertEquals("3", r.readLine());
+        assertNull(r.readLine());
+    }
+
+    public void test_8778372() throws Exception {
+        final PipedInputStream pis = new PipedInputStream();
+        final PipedOutputStream pos = new PipedOutputStream(pis);
+        final Thread t = new Thread() {
+          @Override public void run() {
+              PrintWriter pw = new PrintWriter(new OutputStreamWriter(pos));
+              pw.print("hello, world\r");
+              pw.flush();
+              try {
+                  Thread.sleep(2*60*1000);
+              } catch (InterruptedException ex) {
+                  fail();
+              }
+            }
+        };
+        t.start();
+        BufferedReader br = new BufferedReader(new InputStreamReader(pis));
+        assertEquals("hello, world", br.readLine());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/CharacterTest.java b/luni/src/test/java/libcore/java/lang/CharacterTest.java
index 9438f20..48284d6 100644
--- a/luni/src/test/java/libcore/java/lang/CharacterTest.java
+++ b/luni/src/test/java/libcore/java/lang/CharacterTest.java
@@ -16,100 +16,251 @@
 
 package libcore.java.lang;
 
+import java.lang.reflect.Method;
+
 public class CharacterTest extends junit.framework.TestCase {
-    public void test_valueOfC() {
-        // The JLS requires caching for chars between "\u0000 to \u007f":
-        // http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7
-        // Harmony caches 0-512 and tests for this behavior, so we suppress that test and use this.
-        for (char c = '\u0000'; c <= '\u007f'; ++c) {
-            Character e = new Character(c);
-            Character a = Character.valueOf(c);
-            assertEquals(e, a);
-            assertSame(Character.valueOf(c), Character.valueOf(c));
-        }
-        for (int c = '\u0080'; c <= Character.MAX_VALUE; ++c) {
-            assertEquals(new Character((char) c), Character.valueOf((char) c));
-        }
+  public void test_valueOfC() {
+    // The JLS requires caching for chars between "\u0000 to \u007f":
+    // http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7
+    // Harmony caches 0-512 and tests for this behavior, so we suppress that test and use this.
+    for (char c = '\u0000'; c <= '\u007f'; ++c) {
+      Character e = new Character(c);
+      Character a = Character.valueOf(c);
+      assertEquals(e, a);
+      assertSame(Character.valueOf(c), Character.valueOf(c));
+    }
+    for (int c = '\u0080'; c <= Character.MAX_VALUE; ++c) {
+      assertEquals(new Character((char) c), Character.valueOf((char) c));
+    }
+  }
+
+  public void test_isBmpCodePoint() throws Exception {
+    assertTrue(Character.isBmpCodePoint(0x0000));
+    assertTrue(Character.isBmpCodePoint(0x0666));
+    assertTrue(Character.isBmpCodePoint(0xffff));
+    assertFalse(Character.isBmpCodePoint(0x10000));
+    assertFalse(Character.isBmpCodePoint(-1));
+    assertFalse(Character.isBmpCodePoint(Integer.MAX_VALUE));
+    assertFalse(Character.isBmpCodePoint(Integer.MIN_VALUE));
+  }
+
+  public void test_isSurrogate() throws Exception {
+    assertFalse(Character.isSurrogate('\u0000'));
+    assertFalse(Character.isSurrogate('\u0666'));
+    assertFalse(Character.isSurrogate((char) (Character.MIN_SURROGATE - 1)));
+    for (char ch = Character.MIN_SURROGATE; ch <= Character.MAX_SURROGATE; ++ch) {
+      assertTrue(Character.isSurrogate(ch));
+    }
+    assertFalse(Character.isSurrogate((char) (Character.MAX_SURROGATE + 1)));
+  }
+
+  public void test_highSurrogate() throws Exception {
+    // The behavior for non-supplementary code points (like these two) is undefined.
+    // These are the obvious results if you don't do anything special.
+    assertEquals(0xd7c0, Character.highSurrogate(0x0000));
+    assertEquals(0xd7c1, Character.highSurrogate(0x0666));
+    // These two tests must pass, though.
+    assertEquals(0xd800, Character.highSurrogate(0x010000));
+    assertEquals(0xdbff, Character.highSurrogate(0x10ffff));
+  }
+
+  public void test_lowSurrogate() throws Exception {
+    // The behavior for non-supplementary code points (like these two) is undefined.
+    // These are the obvious results if you don't do anything special.
+    assertEquals(0xdc00, Character.lowSurrogate(0x0000));
+    assertEquals(0xde66, Character.lowSurrogate(0x0666));
+    // These two tests must pass, though.
+    assertEquals(0xdc00, Character.lowSurrogate(0x010000));
+    assertEquals(0xdfff, Character.lowSurrogate(0x10ffff));
+  }
+
+  public void test_getName() throws Exception {
+    // Character.getName requires the corresponding ICU data.
+    // Changed from "NULL" and "BELL" by Unicode 49.2
+    assertEquals("<control-0000>", Character.getName(0x0000));
+    assertEquals("<control-0007>", Character.getName(0x0007));
+    assertEquals("LATIN SMALL LETTER L", Character.getName('l'));
+    // This changed name from Unicode 1.0. Used to be "OPENING...".
+    assertEquals("LEFT CURLY BRACKET", Character.getName('{'));
+    assertEquals("ARABIC-INDIC DIGIT SIX", Character.getName(0x0666));
+    assertEquals("LINEAR B SYLLABLE B008 A", Character.getName(0x010000));
+
+    // Some private use code points.
+    assertEquals("PRIVATE USE AREA E000", Character.getName(0xe000));
+    assertEquals("SUPPLEMENTARY PRIVATE USE AREA A F0000", Character.getName(0xf0000));
+
+    // An unassigned code point.
+    assertNull(Character.getName(0x10ffff));
+
+    try {
+      Character.getName(-1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+    try {
+      Character.getName(Integer.MAX_VALUE);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+    try {
+      Character.getName(Integer.MIN_VALUE);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public void test_compare() throws Exception {
+    assertEquals(0, Character.compare('a', 'a'));
+    assertTrue(Character.compare('a', 'b') < 0);
+    assertTrue(Character.compare('b', 'a') > 0);
+  }
+
+  public void test_UnicodeBlock_all() throws Exception {
+    for (int i = 0; i <= 0x100000; ++i) {
+      Character.UnicodeBlock.of(i);
+    }
+  }
+
+  public void test_UnicodeBlock_of() throws Exception {
+    assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.of(1));
+    assertEquals(Character.UnicodeBlock.HANGUL_JAMO, Character.UnicodeBlock.of(0x1100));
+    assertEquals(Character.UnicodeBlock.CYPRIOT_SYLLABARY, Character.UnicodeBlock.of(0x10800));
+    assertEquals(Character.UnicodeBlock.VARIATION_SELECTORS_SUPPLEMENT, Character.UnicodeBlock.of(0xe0100));
+    // Unicode 4.1.
+    assertEquals(Character.UnicodeBlock.ANCIENT_GREEK_MUSICAL_NOTATION, Character.UnicodeBlock.of(0x1d200));
+    // Unicode 5.0.
+    assertEquals(Character.UnicodeBlock.NKO, Character.UnicodeBlock.of(0x07c0));
+    // Unicode 5.1.
+    assertEquals(Character.UnicodeBlock.SUNDANESE, Character.UnicodeBlock.of(0x1b80));
+    // Unicode 5.2.
+    assertEquals(Character.UnicodeBlock.SAMARITAN, Character.UnicodeBlock.of(0x0800));
+    // Unicode 6.0.
+    assertEquals(Character.UnicodeBlock.MANDAIC, Character.UnicodeBlock.of(0x0840));
+  }
+
+  public void test_UnicodeBlock_forName() throws Exception {
+    // No negative tests here because icu4c is more lenient than the RI;
+    // we'd allow "basic-latin", and "hangul jamo extended b", for example.
+    assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.forName("basic latin"));
+    assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.forName("BaSiC LaTiN"));
+    assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.forName("BasicLatin"));
+    assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.forName("BASIC_LATIN"));
+    assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.forName("basic_LATIN"));
+
+    assertEquals(Character.UnicodeBlock.HANGUL_JAMO_EXTENDED_B, Character.UnicodeBlock.forName("HANGUL_JAMO_EXTENDED_B"));
+    assertEquals(Character.UnicodeBlock.HANGUL_JAMO_EXTENDED_B, Character.UnicodeBlock.forName("HANGUL JAMO EXTENDED-B"));
+
+    // Failure cases.
+    try {
+      Character.UnicodeBlock.forName(null);
+      fail();
+    } catch (NullPointerException expected) {
+    }
+    try {
+      Character.UnicodeBlock.forName("this unicode block does not exist");
+      fail();
+    } catch (IllegalArgumentException expected) {
     }
 
-    public void test_isBmpCodePoint() throws Exception {
-        assertTrue(Character.isBmpCodePoint(0x0000));
-        assertTrue(Character.isBmpCodePoint(0x0666));
-        assertTrue(Character.isBmpCodePoint(0xffff));
-        assertFalse(Character.isBmpCodePoint(0x10000));
-        assertFalse(Character.isBmpCodePoint(-1));
-        assertFalse(Character.isBmpCodePoint(Integer.MAX_VALUE));
-        assertFalse(Character.isBmpCodePoint(Integer.MIN_VALUE));
+    // Renamed blocks.
+    assertEquals(Character.UnicodeBlock.GREEK, Character.UnicodeBlock.forName("Greek"));
+    assertEquals(Character.UnicodeBlock.GREEK, Character.UnicodeBlock.forName("Greek And Coptic"));
+    assertEquals(Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, Character.UnicodeBlock.forName("Combining Marks For Symbols"));
+    assertEquals(Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, Character.UnicodeBlock.forName("Combining Diacritical Marks For Symbols"));
+    assertEquals(Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, Character.UnicodeBlock.forName("COMBINING_MARKS_FOR_SYMBOLS"));
+    assertEquals(Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, Character.UnicodeBlock.forName("Combining Marks for Symbols"));
+    assertEquals(Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, Character.UnicodeBlock.forName("CombiningMarksforSymbols"));
+    assertEquals(Character.UnicodeBlock.CYRILLIC_SUPPLEMENTARY, Character.UnicodeBlock.forName("Cyrillic Supplementary"));
+    assertEquals(Character.UnicodeBlock.CYRILLIC_SUPPLEMENTARY, Character.UnicodeBlock.forName("Cyrillic Supplement"));
+  }
+
+  public void test_isAlphabetic() throws Exception {
+    assertTrue(Character.isAlphabetic('A'));
+    assertTrue(Character.isAlphabetic('a'));
+    assertFalse(Character.isAlphabetic('1'));
+    assertTrue(Character.isAlphabetic(0x113c)); // Hangul j
+  }
+
+  public void test_isIdeographic() throws Exception {
+    assertFalse(Character.isIdeographic('A'));
+    assertFalse(Character.isIdeographic('a'));
+    assertFalse(Character.isIdeographic('1'));
+    assertFalse(Character.isIdeographic(0x113c)); // Hangul j
+
+    assertTrue(Character.isIdeographic(0x4db5));
+    assertTrue(Character.isIdeographic(0x2f999));
+    assertFalse(Character.isIdeographic(0x2f99)); // Kangxi radical shell
+  }
+
+  // http://b/9690863
+  public void test_isDigit_against_icu4c() throws Exception {
+    Method m = Character.class.getDeclaredMethod("isDigit" + "Impl", int.class);
+    m.setAccessible(true);
+    for (int i = 0; i <= 0xffff; ++i) {
+      assertEquals(m.invoke(null, i), Character.isDigit(i));
     }
+  }
 
-    public void test_isSurrogate() throws Exception {
-        assertFalse(Character.isSurrogate('\u0000'));
-        assertFalse(Character.isSurrogate('\u0666'));
-        assertFalse(Character.isSurrogate((char) (Character.MIN_SURROGATE - 1)));
-        for (char ch = Character.MIN_SURROGATE; ch <= Character.MAX_SURROGATE; ++ch) {
-            assertTrue(Character.isSurrogate(ch));
-        }
-        assertFalse(Character.isSurrogate((char) (Character.MAX_SURROGATE + 1)));
+  // http://b/9690863
+  public void test_isIdentifierIgnorable_against_icu4c() throws Exception {
+    Method m = Character.class.getDeclaredMethod("isIdentifierIgnorable" + "Impl", int.class);
+    m.setAccessible(true);
+    for (int i = 0; i <= 0xffff; ++i) {
+      assertEquals(m.invoke(null, i), Character.isIdentifierIgnorable(i));
     }
+  }
 
-    public void test_highSurrogate() throws Exception {
-        // The behavior for non-supplementary code points (like these two) is undefined.
-        // These are the obvious results if you don't do anything special.
-        assertEquals(0xd7c0, Character.highSurrogate(0x0000));
-        assertEquals(0xd7c1, Character.highSurrogate(0x0666));
-        // These two tests must pass, though.
-        assertEquals(0xd800, Character.highSurrogate(0x010000));
-        assertEquals(0xdbff, Character.highSurrogate(0x10ffff));
+  // http://b/9690863
+  public void test_isLetter_against_icu4c() throws Exception {
+    Method m = Character.class.getDeclaredMethod("isLetter" + "Impl", int.class);
+    m.setAccessible(true);
+    for (int i = 0; i <= 0xffff; ++i) {
+      assertEquals(m.invoke(null, i), Character.isLetter(i));
     }
+  }
 
-    public void test_lowSurrogate() throws Exception {
-        // The behavior for non-supplementary code points (like these two) is undefined.
-        // These are the obvious results if you don't do anything special.
-        assertEquals(0xdc00, Character.lowSurrogate(0x0000));
-        assertEquals(0xde66, Character.lowSurrogate(0x0666));
-        // These two tests must pass, though.
-        assertEquals(0xdc00, Character.lowSurrogate(0x010000));
-        assertEquals(0xdfff, Character.lowSurrogate(0x10ffff));
+  // http://b/9690863
+  public void test_isLetterOrDigit_against_icu4c() throws Exception {
+    Method m = Character.class.getDeclaredMethod("isLetterOrDigit" + "Impl", int.class);
+    m.setAccessible(true);
+    for (int i = 0; i <= 0xffff; ++i) {
+      assertEquals(m.invoke(null, i), Character.isLetterOrDigit(i));
     }
+  }
 
-    public void test_getName() throws Exception {
-        // Character.getName requires the corresponding ICU data.
-        // Changed from "NULL" and "BELL" by Unicode 49.2
-        assertEquals("<control-0000>", Character.getName(0x0000));
-        assertEquals("<control-0007>", Character.getName(0x0007));
-        assertEquals("LATIN SMALL LETTER L", Character.getName('l'));
-        // This changed name from Unicode 1.0. Used to be "OPENING...".
-        assertEquals("LEFT CURLY BRACKET", Character.getName('{'));
-        assertEquals("ARABIC-INDIC DIGIT SIX", Character.getName(0x0666));
-        assertEquals("LINEAR B SYLLABLE B008 A", Character.getName(0x010000));
-
-        // Some private use code points.
-        assertEquals("PRIVATE USE AREA E000", Character.getName(0xe000));
-        assertEquals("SUPPLEMENTARY PRIVATE USE AREA A F0000", Character.getName(0xf0000));
-
-        // An unassigned code point.
-        assertNull(Character.getName(0x10ffff));
-
-        try {
-            Character.getName(-1);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            Character.getName(Integer.MAX_VALUE);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            Character.getName(Integer.MIN_VALUE);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
+  // http://b/9690863
+  public void test_isLowerCase_against_icu4c() throws Exception {
+    Method m = Character.class.getDeclaredMethod("isLowerCase" + "Impl", int.class);
+    m.setAccessible(true);
+    for (int i = 0; i <= 0xffff; ++i) {
+      assertEquals(m.invoke(null, i), Character.isLowerCase(i));
     }
+  }
 
-    public void test_compare() throws Exception {
-        assertEquals(0, Character.compare('a', 'a'));
-        assertTrue(Character.compare('a', 'b') < 0);
-        assertTrue(Character.compare('b', 'a') > 0);
+  // http://b/9690863
+  public void test_isSpaceChar_against_icu4c() throws Exception {
+    Method m = Character.class.getDeclaredMethod("isSpaceChar" + "Impl", int.class);
+    m.setAccessible(true);
+    for (int i = 0; i <= 0xffff; ++i) {
+      if((Boolean) m.invoke(null, i) != Character.isSpaceChar(i)) System.out.println(i);
     }
+  }
+
+  // http://b/9690863
+  public void test_isUpperCase_against_icu4c() throws Exception {
+    Method m = Character.class.getDeclaredMethod("isUpperCase" + "Impl", int.class);
+    m.setAccessible(true);
+    for (int i = 0; i <= 0xffff; ++i) {
+      assertEquals(m.invoke(null, i), Character.isUpperCase(i));
+    }
+  }
+
+  // http://b/9690863
+  public void test_isWhitespace_against_icu4c() throws Exception {
+    Method m = Character.class.getDeclaredMethod("isWhitespace" + "Impl", int.class);
+    m.setAccessible(true);
+    for (int i = 0; i <= 0xffff; ++i) {
+      assertEquals(m.invoke(null, i), Character.isWhitespace(i));
+    }
+  }
 }
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 5aa596f..605fd63 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -341,4 +341,11 @@
         // Our fast-path code in String should behave the same...
         assertEquals(expected, new String(bytes, "UTF-8"));
     }
+
+    // https://code.google.com/p/android/issues/detail?id=55129
+    public void test_55129() throws Exception {
+        assertEquals("-h-e-l-l-o- -w-o-r-l-d-", "hello world".replace("", "-"));
+        assertEquals("-w-o-r-l-d-", "hello world".substring(6).replace("", "-"));
+        assertEquals("-*-w-*-o-*-r-*-l-*-d-*-", "hello world".substring(6).replace("", "-*-"));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/ThrowableTest.java b/luni/src/test/java/libcore/java/lang/ThrowableTest.java
index 1906784..7c8ae66 100644
--- a/luni/src/test/java/libcore/java/lang/ThrowableTest.java
+++ b/luni/src/test/java/libcore/java/lang/ThrowableTest.java
@@ -38,10 +38,35 @@
         }
     }
 
+    public void testNonWritableStackTrace() {
+        try {
+            // The 4th argument, writableStackTrace, is false...
+            throw new SuppressionsThrowable("hi", null, true, false);
+        } catch (Throwable th) {
+            assertEquals("hi", th.getMessage());
+
+            // We see an empty stack trace.
+            assertEquals(0, th.getStackTrace().length);
+
+            // setStackTrace is a no-op.
+            th.setStackTrace(new StackTraceElement[] { new StackTraceElement("c", "m", "f", -2) });
+            assertEquals(0, th.getStackTrace().length);
+
+            // fillInStackTrace is a no-op.
+            th.fillInStackTrace();
+            assertEquals(0, th.getStackTrace().length);
+
+            // It's still possible to print an exception with writableStackTrace == false.
+            th.printStackTrace(new PrintWriter(new StringWriter()));
+        }
+    }
+
     private static class SuppressionsThrowable extends Throwable {
+        private static final long serialVersionUID = 202649043897209143L;
+
         public SuppressionsThrowable(String detailMessage, Throwable throwable,
-                boolean enableSuppression) {
-            super(detailMessage, throwable, enableSuppression);
+                boolean enableSuppression, boolean writableStackTrace) {
+            super(detailMessage, throwable, enableSuppression, writableStackTrace);
         }
     }
 
@@ -78,7 +103,7 @@
     }
 
     public void testAddSuppressedWithSuppressionDisabled() {
-        Throwable throwable = new SuppressionsThrowable("foo", null, false);
+        Throwable throwable = new SuppressionsThrowable("foo", null, false, true);
         assertSuppressed(throwable);
         throwable.addSuppressed(new Throwable());
         assertSuppressed(throwable);
@@ -246,7 +271,7 @@
                 + "4696f6e737400104c6a6176612f7574696c2f4c6973743b787070740003666f6f7572001e5b4c6a6"
                 + "176612e6c616e672e537461636b5472616365456c656d656e743b02462a3c3cfd223902000078700"
                 + "00000007078";
-        Throwable throwable = new SuppressionsThrowable("foo", null, false);
+        Throwable throwable = new SuppressionsThrowable("foo", null, false, true);
         throwable.setStackTrace(new StackTraceElement[0]);
         new SerializationTester<Throwable>(throwable, s) {
             @Override protected boolean equals(Throwable a, Throwable b) {
@@ -275,7 +300,7 @@
                 + "0cb5ef71e0200014c0001637400164c6a6176612f7574696c2f436f6c6c656374696f6e3b7870737"
                 + "200136a6176612e7574696c2e41727261794c6973747881d21d99c7619d03000149000473697a657"
                 + "870000000007704000000007871007e000f78";
-        Throwable throwable = new SuppressionsThrowable("foo", null, true);
+        Throwable throwable = new SuppressionsThrowable("foo", null, true, true);
         throwable.setStackTrace(new StackTraceElement[0]);
         new SerializationTester<Throwable>(throwable, s) {
             @Override protected boolean equals(Throwable a, Throwable b) {
diff --git a/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java b/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java
new file mode 100644
index 0000000..60e294b
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java
@@ -0,0 +1,12031 @@
+package libcore.java.lang.reflect;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import junit.framework.TestCase;
+
+public final class Annotations57649Test extends TestCase {
+  // https://code.google.com/p/android/issues/detail?id=57649
+  public void test57649() throws Exception {
+    Thread a = runTest(A.class);
+    Thread b = runTest(B.class);
+    a.join();
+    b.join();
+  }
+
+  private static Thread runTest(final Class<?> c) {
+    Thread t = new Thread(new Runnable() {
+      @Override public void run() {
+        assertEquals(3000, c.getAnnotations().length);
+      }
+    }, c.toString());
+    t.start();
+    return t;
+  }
+
+  @Retention(RetentionPolicy.RUNTIME) @interface A0 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A3 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A4 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A5 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A6 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A7 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A8 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A9 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A10 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A11 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A12 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A13 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A14 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A15 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A16 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A17 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A18 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A19 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A20 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A21 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A22 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A23 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A24 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A25 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A26 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A27 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A28 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A29 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A30 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A31 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A32 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A33 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A34 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A35 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A36 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A37 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A38 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A39 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A40 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A41 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A42 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A43 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A44 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A45 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A46 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A47 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A48 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A49 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A50 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A51 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A52 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A53 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A54 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A55 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A56 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A57 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A58 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A59 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A60 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A61 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A62 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A63 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A64 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A65 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A66 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A67 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A68 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A69 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A70 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A71 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A72 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A73 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A74 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A75 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A76 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A77 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A78 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A79 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A80 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A81 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A82 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A83 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A84 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A85 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A86 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A87 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A88 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A89 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A90 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A91 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A92 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A93 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A94 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A95 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A96 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A97 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A98 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A99 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A100 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A101 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A102 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A103 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A104 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A105 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A106 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A107 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A108 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A109 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A110 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A111 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A112 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A113 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A114 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A115 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A116 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A117 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A118 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A119 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A120 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A121 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A122 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A123 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A124 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A125 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A126 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A127 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A128 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A129 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A130 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A131 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A132 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A133 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A134 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A135 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A136 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A137 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A138 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A139 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A140 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A141 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A142 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A143 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A144 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A145 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A146 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A147 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A148 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A149 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A150 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A151 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A152 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A153 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A154 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A155 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A156 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A157 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A158 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A159 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A160 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A161 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A162 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A163 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A164 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A165 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A166 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A167 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A168 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A169 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A170 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A171 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A172 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A173 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A174 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A175 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A176 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A177 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A178 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A179 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A180 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A181 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A182 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A183 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A184 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A185 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A186 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A187 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A188 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A189 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A190 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A191 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A192 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A193 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A194 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A195 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A196 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A197 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A198 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A199 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A200 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A201 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A202 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A203 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A204 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A205 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A206 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A207 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A208 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A209 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A210 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A211 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A212 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A213 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A214 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A215 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A216 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A217 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A218 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A219 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A220 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A221 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A222 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A223 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A224 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A225 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A226 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A227 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A228 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A229 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A230 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A231 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A232 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A233 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A234 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A235 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A236 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A237 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A238 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A239 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A240 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A241 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A242 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A243 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A244 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A245 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A246 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A247 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A248 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A249 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A250 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A251 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A252 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A253 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A254 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A255 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A256 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A257 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A258 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A259 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A260 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A261 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A262 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A263 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A264 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A265 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A266 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A267 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A268 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A269 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A270 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A271 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A272 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A273 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A274 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A275 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A276 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A277 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A278 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A279 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A280 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A281 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A282 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A283 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A284 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A285 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A286 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A287 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A288 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A289 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A290 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A291 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A292 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A293 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A294 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A295 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A296 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A297 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A298 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A299 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A300 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A301 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A302 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A303 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A304 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A305 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A306 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A307 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A308 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A309 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A310 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A311 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A312 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A313 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A314 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A315 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A316 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A317 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A318 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A319 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A320 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A321 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A322 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A323 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A324 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A325 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A326 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A327 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A328 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A329 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A330 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A331 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A332 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A333 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A334 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A335 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A336 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A337 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A338 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A339 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A340 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A341 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A342 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A343 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A344 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A345 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A346 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A347 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A348 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A349 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A350 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A351 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A352 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A353 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A354 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A355 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A356 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A357 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A358 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A359 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A360 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A361 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A362 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A363 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A364 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A365 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A366 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A367 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A368 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A369 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A370 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A371 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A372 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A373 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A374 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A375 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A376 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A377 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A378 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A379 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A380 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A381 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A382 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A383 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A384 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A385 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A386 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A387 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A388 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A389 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A390 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A391 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A392 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A393 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A394 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A395 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A396 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A397 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A398 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A399 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A400 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A401 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A402 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A403 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A404 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A405 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A406 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A407 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A408 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A409 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A410 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A411 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A412 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A413 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A414 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A415 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A416 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A417 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A418 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A419 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A420 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A421 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A422 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A423 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A424 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A425 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A426 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A427 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A428 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A429 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A430 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A431 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A432 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A433 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A434 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A435 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A436 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A437 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A438 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A439 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A440 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A441 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A442 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A443 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A444 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A445 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A446 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A447 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A448 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A449 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A450 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A451 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A452 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A453 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A454 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A455 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A456 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A457 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A458 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A459 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A460 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A461 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A462 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A463 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A464 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A465 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A466 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A467 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A468 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A469 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A470 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A471 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A472 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A473 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A474 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A475 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A476 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A477 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A478 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A479 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A480 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A481 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A482 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A483 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A484 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A485 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A486 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A487 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A488 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A489 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A490 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A491 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A492 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A493 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A494 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A495 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A496 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A497 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A498 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A499 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A500 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A501 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A502 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A503 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A504 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A505 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A506 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A507 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A508 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A509 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A510 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A511 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A512 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A513 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A514 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A515 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A516 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A517 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A518 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A519 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A520 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A521 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A522 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A523 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A524 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A525 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A526 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A527 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A528 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A529 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A530 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A531 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A532 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A533 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A534 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A535 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A536 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A537 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A538 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A539 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A540 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A541 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A542 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A543 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A544 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A545 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A546 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A547 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A548 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A549 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A550 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A551 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A552 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A553 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A554 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A555 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A556 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A557 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A558 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A559 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A560 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A561 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A562 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A563 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A564 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A565 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A566 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A567 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A568 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A569 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A570 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A571 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A572 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A573 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A574 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A575 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A576 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A577 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A578 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A579 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A580 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A581 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A582 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A583 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A584 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A585 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A586 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A587 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A588 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A589 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A590 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A591 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A592 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A593 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A594 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A595 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A596 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A597 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A598 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A599 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A600 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A601 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A602 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A603 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A604 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A605 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A606 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A607 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A608 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A609 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A610 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A611 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A612 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A613 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A614 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A615 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A616 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A617 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A618 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A619 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A620 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A621 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A622 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A623 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A624 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A625 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A626 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A627 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A628 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A629 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A630 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A631 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A632 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A633 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A634 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A635 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A636 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A637 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A638 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A639 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A640 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A641 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A642 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A643 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A644 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A645 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A646 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A647 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A648 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A649 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A650 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A651 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A652 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A653 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A654 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A655 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A656 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A657 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A658 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A659 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A660 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A661 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A662 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A663 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A664 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A665 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A666 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A667 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A668 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A669 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A670 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A671 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A672 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A673 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A674 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A675 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A676 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A677 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A678 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A679 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A680 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A681 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A682 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A683 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A684 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A685 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A686 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A687 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A688 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A689 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A690 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A691 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A692 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A693 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A694 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A695 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A696 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A697 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A698 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A699 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A700 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A701 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A702 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A703 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A704 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A705 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A706 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A707 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A708 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A709 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A710 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A711 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A712 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A713 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A714 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A715 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A716 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A717 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A718 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A719 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A720 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A721 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A722 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A723 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A724 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A725 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A726 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A727 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A728 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A729 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A730 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A731 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A732 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A733 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A734 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A735 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A736 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A737 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A738 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A739 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A740 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A741 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A742 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A743 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A744 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A745 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A746 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A747 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A748 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A749 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A750 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A751 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A752 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A753 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A754 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A755 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A756 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A757 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A758 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A759 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A760 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A761 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A762 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A763 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A764 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A765 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A766 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A767 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A768 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A769 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A770 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A771 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A772 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A773 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A774 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A775 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A776 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A777 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A778 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A779 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A780 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A781 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A782 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A783 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A784 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A785 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A786 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A787 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A788 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A789 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A790 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A791 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A792 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A793 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A794 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A795 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A796 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A797 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A798 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A799 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A800 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A801 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A802 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A803 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A804 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A805 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A806 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A807 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A808 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A809 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A810 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A811 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A812 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A813 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A814 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A815 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A816 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A817 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A818 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A819 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A820 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A821 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A822 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A823 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A824 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A825 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A826 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A827 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A828 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A829 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A830 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A831 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A832 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A833 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A834 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A835 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A836 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A837 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A838 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A839 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A840 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A841 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A842 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A843 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A844 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A845 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A846 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A847 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A848 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A849 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A850 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A851 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A852 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A853 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A854 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A855 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A856 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A857 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A858 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A859 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A860 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A861 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A862 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A863 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A864 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A865 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A866 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A867 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A868 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A869 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A870 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A871 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A872 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A873 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A874 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A875 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A876 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A877 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A878 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A879 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A880 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A881 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A882 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A883 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A884 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A885 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A886 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A887 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A888 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A889 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A890 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A891 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A892 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A893 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A894 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A895 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A896 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A897 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A898 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A899 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A900 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A901 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A902 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A903 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A904 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A905 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A906 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A907 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A908 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A909 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A910 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A911 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A912 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A913 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A914 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A915 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A916 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A917 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A918 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A919 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A920 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A921 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A922 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A923 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A924 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A925 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A926 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A927 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A928 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A929 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A930 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A931 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A932 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A933 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A934 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A935 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A936 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A937 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A938 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A939 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A940 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A941 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A942 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A943 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A944 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A945 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A946 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A947 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A948 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A949 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A950 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A951 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A952 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A953 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A954 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A955 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A956 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A957 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A958 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A959 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A960 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A961 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A962 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A963 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A964 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A965 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A966 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A967 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A968 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A969 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A970 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A971 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A972 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A973 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A974 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A975 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A976 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A977 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A978 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A979 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A980 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A981 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A982 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A983 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A984 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A985 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A986 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A987 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A988 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A989 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A990 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A991 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A992 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A993 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A994 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A995 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A996 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A997 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A998 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A999 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1000 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1001 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1002 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1003 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1004 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1005 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1006 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1007 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1008 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1009 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1010 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1011 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1012 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1013 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1014 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1015 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1016 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1017 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1018 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1019 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1020 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1021 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1022 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1023 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1024 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1025 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1026 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1027 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1028 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1029 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1030 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1031 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1032 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1033 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1034 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1035 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1036 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1037 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1038 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1039 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1040 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1041 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1042 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1043 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1044 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1045 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1046 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1047 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1048 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1049 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1050 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1051 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1052 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1053 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1054 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1055 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1056 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1057 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1058 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1059 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1060 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1061 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1062 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1063 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1064 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1065 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1066 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1067 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1068 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1069 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1070 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1071 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1072 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1073 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1074 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1075 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1076 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1077 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1078 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1079 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1080 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1081 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1082 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1083 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1084 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1085 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1086 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1087 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1088 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1089 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1090 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1091 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1092 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1093 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1094 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1095 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1096 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1097 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1098 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1099 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1100 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1101 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1102 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1103 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1104 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1105 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1106 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1107 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1108 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1109 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1110 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1111 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1112 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1113 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1114 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1115 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1116 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1117 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1118 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1119 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1120 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1121 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1122 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1123 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1124 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1125 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1126 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1127 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1128 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1129 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1130 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1131 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1132 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1133 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1134 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1135 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1136 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1137 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1138 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1139 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1140 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1141 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1142 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1143 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1144 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1145 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1146 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1147 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1148 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1149 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1150 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1151 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1152 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1153 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1154 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1155 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1156 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1157 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1158 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1159 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1160 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1161 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1162 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1163 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1164 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1165 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1166 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1167 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1168 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1169 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1170 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1171 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1172 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1173 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1174 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1175 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1176 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1177 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1178 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1179 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1180 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1181 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1182 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1183 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1184 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1185 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1186 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1187 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1188 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1189 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1190 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1191 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1192 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1193 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1194 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1195 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1196 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1197 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1198 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1199 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1200 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1201 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1202 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1203 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1204 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1205 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1206 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1207 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1208 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1209 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1210 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1211 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1212 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1213 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1214 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1215 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1216 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1217 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1218 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1219 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1220 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1221 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1222 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1223 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1224 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1225 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1226 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1227 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1228 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1229 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1230 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1231 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1232 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1233 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1234 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1235 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1236 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1237 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1238 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1239 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1240 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1241 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1242 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1243 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1244 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1245 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1246 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1247 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1248 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1249 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1250 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1251 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1252 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1253 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1254 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1255 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1256 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1257 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1258 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1259 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1260 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1261 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1262 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1263 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1264 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1265 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1266 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1267 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1268 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1269 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1270 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1271 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1272 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1273 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1274 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1275 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1276 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1277 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1278 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1279 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1280 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1281 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1282 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1283 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1284 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1285 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1286 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1287 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1288 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1289 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1290 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1291 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1292 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1293 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1294 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1295 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1296 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1297 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1298 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1299 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1300 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1301 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1302 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1303 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1304 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1305 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1306 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1307 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1308 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1309 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1310 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1311 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1312 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1313 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1314 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1315 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1316 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1317 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1318 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1319 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1320 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1321 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1322 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1323 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1324 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1325 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1326 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1327 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1328 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1329 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1330 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1331 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1332 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1333 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1334 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1335 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1336 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1337 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1338 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1339 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1340 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1341 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1342 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1343 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1344 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1345 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1346 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1347 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1348 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1349 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1350 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1351 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1352 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1353 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1354 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1355 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1356 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1357 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1358 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1359 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1360 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1361 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1362 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1363 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1364 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1365 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1366 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1367 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1368 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1369 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1370 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1371 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1372 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1373 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1374 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1375 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1376 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1377 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1378 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1379 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1380 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1381 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1382 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1383 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1384 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1385 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1386 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1387 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1388 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1389 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1390 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1391 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1392 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1393 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1394 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1395 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1396 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1397 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1398 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1399 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1400 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1401 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1402 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1403 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1404 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1405 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1406 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1407 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1408 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1409 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1410 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1411 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1412 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1413 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1414 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1415 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1416 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1417 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1418 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1419 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1420 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1421 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1422 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1423 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1424 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1425 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1426 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1427 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1428 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1429 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1430 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1431 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1432 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1433 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1434 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1435 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1436 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1437 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1438 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1439 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1440 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1441 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1442 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1443 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1444 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1445 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1446 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1447 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1448 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1449 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1450 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1451 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1452 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1453 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1454 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1455 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1456 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1457 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1458 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1459 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1460 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1461 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1462 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1463 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1464 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1465 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1466 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1467 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1468 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1469 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1470 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1471 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1472 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1473 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1474 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1475 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1476 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1477 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1478 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1479 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1480 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1481 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1482 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1483 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1484 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1485 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1486 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1487 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1488 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1489 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1490 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1491 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1492 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1493 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1494 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1495 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1496 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1497 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1498 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1499 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1500 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1501 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1502 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1503 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1504 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1505 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1506 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1507 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1508 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1509 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1510 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1511 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1512 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1513 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1514 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1515 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1516 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1517 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1518 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1519 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1520 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1521 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1522 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1523 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1524 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1525 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1526 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1527 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1528 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1529 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1530 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1531 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1532 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1533 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1534 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1535 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1536 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1537 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1538 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1539 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1540 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1541 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1542 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1543 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1544 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1545 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1546 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1547 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1548 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1549 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1550 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1551 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1552 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1553 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1554 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1555 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1556 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1557 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1558 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1559 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1560 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1561 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1562 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1563 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1564 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1565 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1566 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1567 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1568 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1569 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1570 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1571 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1572 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1573 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1574 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1575 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1576 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1577 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1578 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1579 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1580 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1581 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1582 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1583 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1584 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1585 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1586 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1587 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1588 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1589 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1590 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1591 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1592 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1593 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1594 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1595 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1596 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1597 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1598 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1599 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1600 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1601 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1602 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1603 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1604 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1605 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1606 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1607 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1608 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1609 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1610 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1611 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1612 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1613 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1614 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1615 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1616 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1617 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1618 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1619 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1620 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1621 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1622 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1623 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1624 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1625 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1626 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1627 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1628 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1629 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1630 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1631 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1632 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1633 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1634 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1635 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1636 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1637 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1638 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1639 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1640 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1641 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1642 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1643 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1644 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1645 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1646 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1647 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1648 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1649 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1650 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1651 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1652 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1653 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1654 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1655 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1656 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1657 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1658 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1659 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1660 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1661 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1662 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1663 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1664 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1665 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1666 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1667 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1668 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1669 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1670 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1671 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1672 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1673 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1674 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1675 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1676 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1677 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1678 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1679 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1680 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1681 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1682 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1683 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1684 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1685 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1686 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1687 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1688 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1689 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1690 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1691 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1692 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1693 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1694 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1695 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1696 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1697 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1698 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1699 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1700 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1701 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1702 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1703 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1704 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1705 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1706 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1707 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1708 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1709 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1710 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1711 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1712 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1713 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1714 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1715 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1716 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1717 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1718 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1719 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1720 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1721 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1722 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1723 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1724 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1725 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1726 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1727 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1728 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1729 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1730 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1731 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1732 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1733 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1734 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1735 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1736 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1737 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1738 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1739 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1740 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1741 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1742 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1743 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1744 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1745 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1746 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1747 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1748 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1749 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1750 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1751 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1752 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1753 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1754 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1755 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1756 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1757 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1758 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1759 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1760 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1761 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1762 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1763 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1764 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1765 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1766 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1767 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1768 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1769 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1770 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1771 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1772 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1773 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1774 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1775 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1776 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1777 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1778 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1779 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1780 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1781 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1782 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1783 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1784 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1785 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1786 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1787 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1788 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1789 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1790 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1791 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1792 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1793 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1794 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1795 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1796 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1797 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1798 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1799 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1800 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1801 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1802 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1803 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1804 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1805 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1806 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1807 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1808 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1809 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1810 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1811 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1812 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1813 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1814 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1815 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1816 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1817 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1818 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1819 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1820 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1821 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1822 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1823 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1824 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1825 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1826 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1827 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1828 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1829 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1830 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1831 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1832 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1833 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1834 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1835 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1836 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1837 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1838 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1839 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1840 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1841 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1842 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1843 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1844 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1845 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1846 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1847 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1848 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1849 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1850 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1851 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1852 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1853 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1854 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1855 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1856 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1857 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1858 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1859 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1860 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1861 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1862 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1863 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1864 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1865 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1866 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1867 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1868 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1869 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1870 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1871 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1872 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1873 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1874 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1875 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1876 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1877 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1878 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1879 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1880 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1881 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1882 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1883 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1884 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1885 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1886 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1887 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1888 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1889 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1890 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1891 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1892 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1893 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1894 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1895 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1896 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1897 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1898 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1899 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1900 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1901 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1902 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1903 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1904 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1905 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1906 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1907 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1908 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1909 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1910 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1911 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1912 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1913 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1914 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1915 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1916 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1917 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1918 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1919 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1920 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1921 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1922 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1923 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1924 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1925 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1926 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1927 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1928 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1929 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1930 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1931 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1932 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1933 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1934 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1935 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1936 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1937 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1938 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1939 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1940 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1941 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1942 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1943 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1944 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1945 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1946 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1947 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1948 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1949 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1950 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1951 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1952 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1953 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1954 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1955 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1956 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1957 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1958 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1959 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1960 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1961 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1962 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1963 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1964 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1965 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1966 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1967 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1968 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1969 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1970 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1971 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1972 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1973 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1974 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1975 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1976 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1977 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1978 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1979 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1980 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1981 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1982 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1983 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1984 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1985 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1986 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1987 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1988 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1989 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1990 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1991 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1992 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1993 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1994 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1995 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1996 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1997 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1998 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A1999 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2000 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2001 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2002 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2003 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2004 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2005 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2006 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2007 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2008 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2009 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2010 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2011 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2012 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2013 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2014 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2015 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2016 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2017 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2018 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2019 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2020 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2021 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2022 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2023 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2024 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2025 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2026 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2027 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2028 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2029 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2030 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2031 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2032 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2033 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2034 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2035 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2036 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2037 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2038 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2039 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2040 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2041 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2042 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2043 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2044 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2045 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2046 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2047 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2048 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2049 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2050 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2051 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2052 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2053 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2054 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2055 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2056 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2057 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2058 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2059 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2060 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2061 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2062 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2063 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2064 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2065 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2066 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2067 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2068 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2069 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2070 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2071 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2072 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2073 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2074 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2075 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2076 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2077 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2078 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2079 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2080 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2081 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2082 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2083 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2084 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2085 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2086 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2087 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2088 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2089 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2090 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2091 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2092 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2093 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2094 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2095 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2096 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2097 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2098 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2099 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2100 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2101 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2102 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2103 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2104 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2105 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2106 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2107 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2108 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2109 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2110 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2111 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2112 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2113 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2114 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2115 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2116 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2117 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2118 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2119 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2120 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2121 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2122 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2123 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2124 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2125 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2126 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2127 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2128 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2129 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2130 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2131 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2132 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2133 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2134 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2135 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2136 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2137 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2138 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2139 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2140 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2141 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2142 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2143 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2144 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2145 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2146 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2147 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2148 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2149 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2150 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2151 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2152 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2153 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2154 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2155 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2156 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2157 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2158 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2159 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2160 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2161 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2162 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2163 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2164 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2165 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2166 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2167 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2168 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2169 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2170 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2171 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2172 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2173 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2174 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2175 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2176 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2177 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2178 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2179 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2180 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2181 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2182 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2183 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2184 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2185 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2186 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2187 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2188 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2189 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2190 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2191 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2192 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2193 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2194 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2195 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2196 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2197 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2198 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2199 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2200 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2201 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2202 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2203 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2204 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2205 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2206 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2207 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2208 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2209 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2210 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2211 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2212 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2213 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2214 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2215 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2216 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2217 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2218 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2219 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2220 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2221 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2222 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2223 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2224 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2225 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2226 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2227 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2228 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2229 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2230 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2231 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2232 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2233 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2234 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2235 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2236 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2237 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2238 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2239 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2240 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2241 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2242 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2243 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2244 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2245 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2246 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2247 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2248 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2249 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2250 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2251 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2252 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2253 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2254 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2255 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2256 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2257 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2258 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2259 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2260 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2261 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2262 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2263 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2264 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2265 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2266 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2267 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2268 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2269 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2270 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2271 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2272 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2273 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2274 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2275 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2276 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2277 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2278 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2279 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2280 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2281 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2282 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2283 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2284 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2285 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2286 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2287 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2288 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2289 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2290 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2291 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2292 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2293 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2294 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2295 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2296 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2297 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2298 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2299 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2300 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2301 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2302 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2303 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2304 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2305 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2306 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2307 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2308 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2309 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2310 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2311 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2312 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2313 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2314 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2315 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2316 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2317 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2318 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2319 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2320 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2321 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2322 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2323 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2324 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2325 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2326 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2327 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2328 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2329 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2330 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2331 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2332 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2333 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2334 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2335 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2336 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2337 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2338 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2339 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2340 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2341 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2342 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2343 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2344 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2345 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2346 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2347 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2348 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2349 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2350 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2351 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2352 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2353 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2354 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2355 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2356 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2357 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2358 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2359 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2360 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2361 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2362 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2363 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2364 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2365 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2366 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2367 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2368 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2369 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2370 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2371 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2372 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2373 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2374 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2375 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2376 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2377 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2378 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2379 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2380 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2381 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2382 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2383 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2384 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2385 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2386 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2387 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2388 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2389 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2390 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2391 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2392 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2393 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2394 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2395 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2396 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2397 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2398 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2399 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2400 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2401 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2402 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2403 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2404 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2405 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2406 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2407 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2408 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2409 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2410 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2411 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2412 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2413 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2414 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2415 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2416 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2417 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2418 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2419 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2420 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2421 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2422 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2423 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2424 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2425 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2426 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2427 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2428 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2429 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2430 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2431 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2432 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2433 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2434 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2435 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2436 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2437 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2438 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2439 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2440 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2441 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2442 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2443 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2444 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2445 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2446 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2447 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2448 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2449 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2450 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2451 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2452 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2453 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2454 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2455 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2456 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2457 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2458 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2459 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2460 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2461 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2462 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2463 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2464 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2465 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2466 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2467 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2468 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2469 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2470 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2471 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2472 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2473 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2474 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2475 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2476 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2477 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2478 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2479 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2480 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2481 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2482 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2483 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2484 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2485 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2486 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2487 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2488 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2489 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2490 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2491 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2492 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2493 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2494 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2495 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2496 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2497 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2498 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2499 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2500 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2501 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2502 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2503 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2504 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2505 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2506 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2507 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2508 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2509 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2510 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2511 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2512 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2513 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2514 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2515 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2516 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2517 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2518 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2519 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2520 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2521 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2522 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2523 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2524 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2525 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2526 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2527 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2528 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2529 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2530 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2531 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2532 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2533 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2534 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2535 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2536 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2537 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2538 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2539 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2540 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2541 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2542 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2543 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2544 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2545 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2546 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2547 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2548 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2549 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2550 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2551 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2552 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2553 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2554 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2555 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2556 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2557 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2558 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2559 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2560 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2561 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2562 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2563 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2564 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2565 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2566 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2567 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2568 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2569 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2570 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2571 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2572 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2573 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2574 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2575 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2576 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2577 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2578 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2579 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2580 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2581 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2582 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2583 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2584 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2585 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2586 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2587 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2588 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2589 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2590 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2591 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2592 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2593 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2594 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2595 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2596 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2597 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2598 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2599 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2600 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2601 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2602 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2603 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2604 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2605 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2606 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2607 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2608 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2609 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2610 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2611 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2612 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2613 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2614 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2615 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2616 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2617 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2618 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2619 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2620 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2621 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2622 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2623 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2624 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2625 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2626 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2627 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2628 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2629 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2630 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2631 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2632 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2633 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2634 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2635 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2636 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2637 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2638 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2639 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2640 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2641 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2642 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2643 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2644 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2645 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2646 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2647 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2648 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2649 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2650 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2651 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2652 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2653 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2654 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2655 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2656 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2657 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2658 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2659 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2660 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2661 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2662 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2663 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2664 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2665 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2666 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2667 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2668 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2669 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2670 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2671 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2672 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2673 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2674 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2675 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2676 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2677 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2678 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2679 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2680 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2681 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2682 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2683 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2684 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2685 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2686 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2687 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2688 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2689 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2690 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2691 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2692 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2693 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2694 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2695 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2696 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2697 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2698 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2699 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2700 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2701 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2702 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2703 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2704 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2705 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2706 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2707 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2708 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2709 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2710 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2711 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2712 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2713 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2714 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2715 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2716 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2717 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2718 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2719 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2720 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2721 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2722 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2723 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2724 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2725 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2726 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2727 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2728 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2729 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2730 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2731 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2732 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2733 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2734 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2735 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2736 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2737 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2738 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2739 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2740 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2741 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2742 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2743 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2744 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2745 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2746 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2747 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2748 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2749 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2750 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2751 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2752 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2753 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2754 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2755 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2756 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2757 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2758 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2759 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2760 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2761 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2762 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2763 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2764 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2765 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2766 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2767 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2768 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2769 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2770 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2771 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2772 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2773 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2774 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2775 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2776 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2777 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2778 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2779 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2780 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2781 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2782 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2783 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2784 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2785 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2786 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2787 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2788 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2789 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2790 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2791 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2792 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2793 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2794 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2795 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2796 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2797 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2798 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2799 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2800 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2801 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2802 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2803 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2804 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2805 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2806 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2807 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2808 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2809 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2810 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2811 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2812 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2813 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2814 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2815 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2816 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2817 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2818 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2819 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2820 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2821 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2822 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2823 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2824 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2825 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2826 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2827 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2828 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2829 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2830 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2831 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2832 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2833 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2834 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2835 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2836 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2837 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2838 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2839 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2840 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2841 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2842 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2843 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2844 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2845 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2846 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2847 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2848 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2849 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2850 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2851 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2852 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2853 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2854 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2855 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2856 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2857 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2858 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2859 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2860 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2861 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2862 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2863 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2864 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2865 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2866 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2867 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2868 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2869 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2870 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2871 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2872 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2873 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2874 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2875 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2876 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2877 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2878 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2879 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2880 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2881 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2882 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2883 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2884 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2885 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2886 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2887 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2888 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2889 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2890 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2891 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2892 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2893 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2894 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2895 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2896 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2897 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2898 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2899 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2900 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2901 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2902 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2903 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2904 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2905 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2906 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2907 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2908 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2909 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2910 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2911 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2912 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2913 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2914 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2915 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2916 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2917 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2918 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2919 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2920 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2921 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2922 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2923 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2924 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2925 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2926 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2927 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2928 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2929 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2930 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2931 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2932 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2933 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2934 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2935 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2936 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2937 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2938 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2939 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2940 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2941 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2942 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2943 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2944 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2945 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2946 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2947 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2948 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2949 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2950 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2951 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2952 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2953 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2954 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2955 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2956 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2957 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2958 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2959 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2960 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2961 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2962 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2963 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2964 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2965 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2966 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2967 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2968 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2969 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2970 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2971 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2972 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2973 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2974 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2975 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2976 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2977 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2978 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2979 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2980 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2981 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2982 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2983 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2984 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2985 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2986 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2987 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2988 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2989 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2990 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2991 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2992 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2993 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2994 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2995 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2996 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2997 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2998 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface A2999 {}
+
+  @A0
+  @A1
+  @A2
+  @A3
+  @A4
+  @A5
+  @A6
+  @A7
+  @A8
+  @A9
+  @A10
+  @A11
+  @A12
+  @A13
+  @A14
+  @A15
+  @A16
+  @A17
+  @A18
+  @A19
+  @A20
+  @A21
+  @A22
+  @A23
+  @A24
+  @A25
+  @A26
+  @A27
+  @A28
+  @A29
+  @A30
+  @A31
+  @A32
+  @A33
+  @A34
+  @A35
+  @A36
+  @A37
+  @A38
+  @A39
+  @A40
+  @A41
+  @A42
+  @A43
+  @A44
+  @A45
+  @A46
+  @A47
+  @A48
+  @A49
+  @A50
+  @A51
+  @A52
+  @A53
+  @A54
+  @A55
+  @A56
+  @A57
+  @A58
+  @A59
+  @A60
+  @A61
+  @A62
+  @A63
+  @A64
+  @A65
+  @A66
+  @A67
+  @A68
+  @A69
+  @A70
+  @A71
+  @A72
+  @A73
+  @A74
+  @A75
+  @A76
+  @A77
+  @A78
+  @A79
+  @A80
+  @A81
+  @A82
+  @A83
+  @A84
+  @A85
+  @A86
+  @A87
+  @A88
+  @A89
+  @A90
+  @A91
+  @A92
+  @A93
+  @A94
+  @A95
+  @A96
+  @A97
+  @A98
+  @A99
+  @A100
+  @A101
+  @A102
+  @A103
+  @A104
+  @A105
+  @A106
+  @A107
+  @A108
+  @A109
+  @A110
+  @A111
+  @A112
+  @A113
+  @A114
+  @A115
+  @A116
+  @A117
+  @A118
+  @A119
+  @A120
+  @A121
+  @A122
+  @A123
+  @A124
+  @A125
+  @A126
+  @A127
+  @A128
+  @A129
+  @A130
+  @A131
+  @A132
+  @A133
+  @A134
+  @A135
+  @A136
+  @A137
+  @A138
+  @A139
+  @A140
+  @A141
+  @A142
+  @A143
+  @A144
+  @A145
+  @A146
+  @A147
+  @A148
+  @A149
+  @A150
+  @A151
+  @A152
+  @A153
+  @A154
+  @A155
+  @A156
+  @A157
+  @A158
+  @A159
+  @A160
+  @A161
+  @A162
+  @A163
+  @A164
+  @A165
+  @A166
+  @A167
+  @A168
+  @A169
+  @A170
+  @A171
+  @A172
+  @A173
+  @A174
+  @A175
+  @A176
+  @A177
+  @A178
+  @A179
+  @A180
+  @A181
+  @A182
+  @A183
+  @A184
+  @A185
+  @A186
+  @A187
+  @A188
+  @A189
+  @A190
+  @A191
+  @A192
+  @A193
+  @A194
+  @A195
+  @A196
+  @A197
+  @A198
+  @A199
+  @A200
+  @A201
+  @A202
+  @A203
+  @A204
+  @A205
+  @A206
+  @A207
+  @A208
+  @A209
+  @A210
+  @A211
+  @A212
+  @A213
+  @A214
+  @A215
+  @A216
+  @A217
+  @A218
+  @A219
+  @A220
+  @A221
+  @A222
+  @A223
+  @A224
+  @A225
+  @A226
+  @A227
+  @A228
+  @A229
+  @A230
+  @A231
+  @A232
+  @A233
+  @A234
+  @A235
+  @A236
+  @A237
+  @A238
+  @A239
+  @A240
+  @A241
+  @A242
+  @A243
+  @A244
+  @A245
+  @A246
+  @A247
+  @A248
+  @A249
+  @A250
+  @A251
+  @A252
+  @A253
+  @A254
+  @A255
+  @A256
+  @A257
+  @A258
+  @A259
+  @A260
+  @A261
+  @A262
+  @A263
+  @A264
+  @A265
+  @A266
+  @A267
+  @A268
+  @A269
+  @A270
+  @A271
+  @A272
+  @A273
+  @A274
+  @A275
+  @A276
+  @A277
+  @A278
+  @A279
+  @A280
+  @A281
+  @A282
+  @A283
+  @A284
+  @A285
+  @A286
+  @A287
+  @A288
+  @A289
+  @A290
+  @A291
+  @A292
+  @A293
+  @A294
+  @A295
+  @A296
+  @A297
+  @A298
+  @A299
+  @A300
+  @A301
+  @A302
+  @A303
+  @A304
+  @A305
+  @A306
+  @A307
+  @A308
+  @A309
+  @A310
+  @A311
+  @A312
+  @A313
+  @A314
+  @A315
+  @A316
+  @A317
+  @A318
+  @A319
+  @A320
+  @A321
+  @A322
+  @A323
+  @A324
+  @A325
+  @A326
+  @A327
+  @A328
+  @A329
+  @A330
+  @A331
+  @A332
+  @A333
+  @A334
+  @A335
+  @A336
+  @A337
+  @A338
+  @A339
+  @A340
+  @A341
+  @A342
+  @A343
+  @A344
+  @A345
+  @A346
+  @A347
+  @A348
+  @A349
+  @A350
+  @A351
+  @A352
+  @A353
+  @A354
+  @A355
+  @A356
+  @A357
+  @A358
+  @A359
+  @A360
+  @A361
+  @A362
+  @A363
+  @A364
+  @A365
+  @A366
+  @A367
+  @A368
+  @A369
+  @A370
+  @A371
+  @A372
+  @A373
+  @A374
+  @A375
+  @A376
+  @A377
+  @A378
+  @A379
+  @A380
+  @A381
+  @A382
+  @A383
+  @A384
+  @A385
+  @A386
+  @A387
+  @A388
+  @A389
+  @A390
+  @A391
+  @A392
+  @A393
+  @A394
+  @A395
+  @A396
+  @A397
+  @A398
+  @A399
+  @A400
+  @A401
+  @A402
+  @A403
+  @A404
+  @A405
+  @A406
+  @A407
+  @A408
+  @A409
+  @A410
+  @A411
+  @A412
+  @A413
+  @A414
+  @A415
+  @A416
+  @A417
+  @A418
+  @A419
+  @A420
+  @A421
+  @A422
+  @A423
+  @A424
+  @A425
+  @A426
+  @A427
+  @A428
+  @A429
+  @A430
+  @A431
+  @A432
+  @A433
+  @A434
+  @A435
+  @A436
+  @A437
+  @A438
+  @A439
+  @A440
+  @A441
+  @A442
+  @A443
+  @A444
+  @A445
+  @A446
+  @A447
+  @A448
+  @A449
+  @A450
+  @A451
+  @A452
+  @A453
+  @A454
+  @A455
+  @A456
+  @A457
+  @A458
+  @A459
+  @A460
+  @A461
+  @A462
+  @A463
+  @A464
+  @A465
+  @A466
+  @A467
+  @A468
+  @A469
+  @A470
+  @A471
+  @A472
+  @A473
+  @A474
+  @A475
+  @A476
+  @A477
+  @A478
+  @A479
+  @A480
+  @A481
+  @A482
+  @A483
+  @A484
+  @A485
+  @A486
+  @A487
+  @A488
+  @A489
+  @A490
+  @A491
+  @A492
+  @A493
+  @A494
+  @A495
+  @A496
+  @A497
+  @A498
+  @A499
+  @A500
+  @A501
+  @A502
+  @A503
+  @A504
+  @A505
+  @A506
+  @A507
+  @A508
+  @A509
+  @A510
+  @A511
+  @A512
+  @A513
+  @A514
+  @A515
+  @A516
+  @A517
+  @A518
+  @A519
+  @A520
+  @A521
+  @A522
+  @A523
+  @A524
+  @A525
+  @A526
+  @A527
+  @A528
+  @A529
+  @A530
+  @A531
+  @A532
+  @A533
+  @A534
+  @A535
+  @A536
+  @A537
+  @A538
+  @A539
+  @A540
+  @A541
+  @A542
+  @A543
+  @A544
+  @A545
+  @A546
+  @A547
+  @A548
+  @A549
+  @A550
+  @A551
+  @A552
+  @A553
+  @A554
+  @A555
+  @A556
+  @A557
+  @A558
+  @A559
+  @A560
+  @A561
+  @A562
+  @A563
+  @A564
+  @A565
+  @A566
+  @A567
+  @A568
+  @A569
+  @A570
+  @A571
+  @A572
+  @A573
+  @A574
+  @A575
+  @A576
+  @A577
+  @A578
+  @A579
+  @A580
+  @A581
+  @A582
+  @A583
+  @A584
+  @A585
+  @A586
+  @A587
+  @A588
+  @A589
+  @A590
+  @A591
+  @A592
+  @A593
+  @A594
+  @A595
+  @A596
+  @A597
+  @A598
+  @A599
+  @A600
+  @A601
+  @A602
+  @A603
+  @A604
+  @A605
+  @A606
+  @A607
+  @A608
+  @A609
+  @A610
+  @A611
+  @A612
+  @A613
+  @A614
+  @A615
+  @A616
+  @A617
+  @A618
+  @A619
+  @A620
+  @A621
+  @A622
+  @A623
+  @A624
+  @A625
+  @A626
+  @A627
+  @A628
+  @A629
+  @A630
+  @A631
+  @A632
+  @A633
+  @A634
+  @A635
+  @A636
+  @A637
+  @A638
+  @A639
+  @A640
+  @A641
+  @A642
+  @A643
+  @A644
+  @A645
+  @A646
+  @A647
+  @A648
+  @A649
+  @A650
+  @A651
+  @A652
+  @A653
+  @A654
+  @A655
+  @A656
+  @A657
+  @A658
+  @A659
+  @A660
+  @A661
+  @A662
+  @A663
+  @A664
+  @A665
+  @A666
+  @A667
+  @A668
+  @A669
+  @A670
+  @A671
+  @A672
+  @A673
+  @A674
+  @A675
+  @A676
+  @A677
+  @A678
+  @A679
+  @A680
+  @A681
+  @A682
+  @A683
+  @A684
+  @A685
+  @A686
+  @A687
+  @A688
+  @A689
+  @A690
+  @A691
+  @A692
+  @A693
+  @A694
+  @A695
+  @A696
+  @A697
+  @A698
+  @A699
+  @A700
+  @A701
+  @A702
+  @A703
+  @A704
+  @A705
+  @A706
+  @A707
+  @A708
+  @A709
+  @A710
+  @A711
+  @A712
+  @A713
+  @A714
+  @A715
+  @A716
+  @A717
+  @A718
+  @A719
+  @A720
+  @A721
+  @A722
+  @A723
+  @A724
+  @A725
+  @A726
+  @A727
+  @A728
+  @A729
+  @A730
+  @A731
+  @A732
+  @A733
+  @A734
+  @A735
+  @A736
+  @A737
+  @A738
+  @A739
+  @A740
+  @A741
+  @A742
+  @A743
+  @A744
+  @A745
+  @A746
+  @A747
+  @A748
+  @A749
+  @A750
+  @A751
+  @A752
+  @A753
+  @A754
+  @A755
+  @A756
+  @A757
+  @A758
+  @A759
+  @A760
+  @A761
+  @A762
+  @A763
+  @A764
+  @A765
+  @A766
+  @A767
+  @A768
+  @A769
+  @A770
+  @A771
+  @A772
+  @A773
+  @A774
+  @A775
+  @A776
+  @A777
+  @A778
+  @A779
+  @A780
+  @A781
+  @A782
+  @A783
+  @A784
+  @A785
+  @A786
+  @A787
+  @A788
+  @A789
+  @A790
+  @A791
+  @A792
+  @A793
+  @A794
+  @A795
+  @A796
+  @A797
+  @A798
+  @A799
+  @A800
+  @A801
+  @A802
+  @A803
+  @A804
+  @A805
+  @A806
+  @A807
+  @A808
+  @A809
+  @A810
+  @A811
+  @A812
+  @A813
+  @A814
+  @A815
+  @A816
+  @A817
+  @A818
+  @A819
+  @A820
+  @A821
+  @A822
+  @A823
+  @A824
+  @A825
+  @A826
+  @A827
+  @A828
+  @A829
+  @A830
+  @A831
+  @A832
+  @A833
+  @A834
+  @A835
+  @A836
+  @A837
+  @A838
+  @A839
+  @A840
+  @A841
+  @A842
+  @A843
+  @A844
+  @A845
+  @A846
+  @A847
+  @A848
+  @A849
+  @A850
+  @A851
+  @A852
+  @A853
+  @A854
+  @A855
+  @A856
+  @A857
+  @A858
+  @A859
+  @A860
+  @A861
+  @A862
+  @A863
+  @A864
+  @A865
+  @A866
+  @A867
+  @A868
+  @A869
+  @A870
+  @A871
+  @A872
+  @A873
+  @A874
+  @A875
+  @A876
+  @A877
+  @A878
+  @A879
+  @A880
+  @A881
+  @A882
+  @A883
+  @A884
+  @A885
+  @A886
+  @A887
+  @A888
+  @A889
+  @A890
+  @A891
+  @A892
+  @A893
+  @A894
+  @A895
+  @A896
+  @A897
+  @A898
+  @A899
+  @A900
+  @A901
+  @A902
+  @A903
+  @A904
+  @A905
+  @A906
+  @A907
+  @A908
+  @A909
+  @A910
+  @A911
+  @A912
+  @A913
+  @A914
+  @A915
+  @A916
+  @A917
+  @A918
+  @A919
+  @A920
+  @A921
+  @A922
+  @A923
+  @A924
+  @A925
+  @A926
+  @A927
+  @A928
+  @A929
+  @A930
+  @A931
+  @A932
+  @A933
+  @A934
+  @A935
+  @A936
+  @A937
+  @A938
+  @A939
+  @A940
+  @A941
+  @A942
+  @A943
+  @A944
+  @A945
+  @A946
+  @A947
+  @A948
+  @A949
+  @A950
+  @A951
+  @A952
+  @A953
+  @A954
+  @A955
+  @A956
+  @A957
+  @A958
+  @A959
+  @A960
+  @A961
+  @A962
+  @A963
+  @A964
+  @A965
+  @A966
+  @A967
+  @A968
+  @A969
+  @A970
+  @A971
+  @A972
+  @A973
+  @A974
+  @A975
+  @A976
+  @A977
+  @A978
+  @A979
+  @A980
+  @A981
+  @A982
+  @A983
+  @A984
+  @A985
+  @A986
+  @A987
+  @A988
+  @A989
+  @A990
+  @A991
+  @A992
+  @A993
+  @A994
+  @A995
+  @A996
+  @A997
+  @A998
+  @A999
+  @A1000
+  @A1001
+  @A1002
+  @A1003
+  @A1004
+  @A1005
+  @A1006
+  @A1007
+  @A1008
+  @A1009
+  @A1010
+  @A1011
+  @A1012
+  @A1013
+  @A1014
+  @A1015
+  @A1016
+  @A1017
+  @A1018
+  @A1019
+  @A1020
+  @A1021
+  @A1022
+  @A1023
+  @A1024
+  @A1025
+  @A1026
+  @A1027
+  @A1028
+  @A1029
+  @A1030
+  @A1031
+  @A1032
+  @A1033
+  @A1034
+  @A1035
+  @A1036
+  @A1037
+  @A1038
+  @A1039
+  @A1040
+  @A1041
+  @A1042
+  @A1043
+  @A1044
+  @A1045
+  @A1046
+  @A1047
+  @A1048
+  @A1049
+  @A1050
+  @A1051
+  @A1052
+  @A1053
+  @A1054
+  @A1055
+  @A1056
+  @A1057
+  @A1058
+  @A1059
+  @A1060
+  @A1061
+  @A1062
+  @A1063
+  @A1064
+  @A1065
+  @A1066
+  @A1067
+  @A1068
+  @A1069
+  @A1070
+  @A1071
+  @A1072
+  @A1073
+  @A1074
+  @A1075
+  @A1076
+  @A1077
+  @A1078
+  @A1079
+  @A1080
+  @A1081
+  @A1082
+  @A1083
+  @A1084
+  @A1085
+  @A1086
+  @A1087
+  @A1088
+  @A1089
+  @A1090
+  @A1091
+  @A1092
+  @A1093
+  @A1094
+  @A1095
+  @A1096
+  @A1097
+  @A1098
+  @A1099
+  @A1100
+  @A1101
+  @A1102
+  @A1103
+  @A1104
+  @A1105
+  @A1106
+  @A1107
+  @A1108
+  @A1109
+  @A1110
+  @A1111
+  @A1112
+  @A1113
+  @A1114
+  @A1115
+  @A1116
+  @A1117
+  @A1118
+  @A1119
+  @A1120
+  @A1121
+  @A1122
+  @A1123
+  @A1124
+  @A1125
+  @A1126
+  @A1127
+  @A1128
+  @A1129
+  @A1130
+  @A1131
+  @A1132
+  @A1133
+  @A1134
+  @A1135
+  @A1136
+  @A1137
+  @A1138
+  @A1139
+  @A1140
+  @A1141
+  @A1142
+  @A1143
+  @A1144
+  @A1145
+  @A1146
+  @A1147
+  @A1148
+  @A1149
+  @A1150
+  @A1151
+  @A1152
+  @A1153
+  @A1154
+  @A1155
+  @A1156
+  @A1157
+  @A1158
+  @A1159
+  @A1160
+  @A1161
+  @A1162
+  @A1163
+  @A1164
+  @A1165
+  @A1166
+  @A1167
+  @A1168
+  @A1169
+  @A1170
+  @A1171
+  @A1172
+  @A1173
+  @A1174
+  @A1175
+  @A1176
+  @A1177
+  @A1178
+  @A1179
+  @A1180
+  @A1181
+  @A1182
+  @A1183
+  @A1184
+  @A1185
+  @A1186
+  @A1187
+  @A1188
+  @A1189
+  @A1190
+  @A1191
+  @A1192
+  @A1193
+  @A1194
+  @A1195
+  @A1196
+  @A1197
+  @A1198
+  @A1199
+  @A1200
+  @A1201
+  @A1202
+  @A1203
+  @A1204
+  @A1205
+  @A1206
+  @A1207
+  @A1208
+  @A1209
+  @A1210
+  @A1211
+  @A1212
+  @A1213
+  @A1214
+  @A1215
+  @A1216
+  @A1217
+  @A1218
+  @A1219
+  @A1220
+  @A1221
+  @A1222
+  @A1223
+  @A1224
+  @A1225
+  @A1226
+  @A1227
+  @A1228
+  @A1229
+  @A1230
+  @A1231
+  @A1232
+  @A1233
+  @A1234
+  @A1235
+  @A1236
+  @A1237
+  @A1238
+  @A1239
+  @A1240
+  @A1241
+  @A1242
+  @A1243
+  @A1244
+  @A1245
+  @A1246
+  @A1247
+  @A1248
+  @A1249
+  @A1250
+  @A1251
+  @A1252
+  @A1253
+  @A1254
+  @A1255
+  @A1256
+  @A1257
+  @A1258
+  @A1259
+  @A1260
+  @A1261
+  @A1262
+  @A1263
+  @A1264
+  @A1265
+  @A1266
+  @A1267
+  @A1268
+  @A1269
+  @A1270
+  @A1271
+  @A1272
+  @A1273
+  @A1274
+  @A1275
+  @A1276
+  @A1277
+  @A1278
+  @A1279
+  @A1280
+  @A1281
+  @A1282
+  @A1283
+  @A1284
+  @A1285
+  @A1286
+  @A1287
+  @A1288
+  @A1289
+  @A1290
+  @A1291
+  @A1292
+  @A1293
+  @A1294
+  @A1295
+  @A1296
+  @A1297
+  @A1298
+  @A1299
+  @A1300
+  @A1301
+  @A1302
+  @A1303
+  @A1304
+  @A1305
+  @A1306
+  @A1307
+  @A1308
+  @A1309
+  @A1310
+  @A1311
+  @A1312
+  @A1313
+  @A1314
+  @A1315
+  @A1316
+  @A1317
+  @A1318
+  @A1319
+  @A1320
+  @A1321
+  @A1322
+  @A1323
+  @A1324
+  @A1325
+  @A1326
+  @A1327
+  @A1328
+  @A1329
+  @A1330
+  @A1331
+  @A1332
+  @A1333
+  @A1334
+  @A1335
+  @A1336
+  @A1337
+  @A1338
+  @A1339
+  @A1340
+  @A1341
+  @A1342
+  @A1343
+  @A1344
+  @A1345
+  @A1346
+  @A1347
+  @A1348
+  @A1349
+  @A1350
+  @A1351
+  @A1352
+  @A1353
+  @A1354
+  @A1355
+  @A1356
+  @A1357
+  @A1358
+  @A1359
+  @A1360
+  @A1361
+  @A1362
+  @A1363
+  @A1364
+  @A1365
+  @A1366
+  @A1367
+  @A1368
+  @A1369
+  @A1370
+  @A1371
+  @A1372
+  @A1373
+  @A1374
+  @A1375
+  @A1376
+  @A1377
+  @A1378
+  @A1379
+  @A1380
+  @A1381
+  @A1382
+  @A1383
+  @A1384
+  @A1385
+  @A1386
+  @A1387
+  @A1388
+  @A1389
+  @A1390
+  @A1391
+  @A1392
+  @A1393
+  @A1394
+  @A1395
+  @A1396
+  @A1397
+  @A1398
+  @A1399
+  @A1400
+  @A1401
+  @A1402
+  @A1403
+  @A1404
+  @A1405
+  @A1406
+  @A1407
+  @A1408
+  @A1409
+  @A1410
+  @A1411
+  @A1412
+  @A1413
+  @A1414
+  @A1415
+  @A1416
+  @A1417
+  @A1418
+  @A1419
+  @A1420
+  @A1421
+  @A1422
+  @A1423
+  @A1424
+  @A1425
+  @A1426
+  @A1427
+  @A1428
+  @A1429
+  @A1430
+  @A1431
+  @A1432
+  @A1433
+  @A1434
+  @A1435
+  @A1436
+  @A1437
+  @A1438
+  @A1439
+  @A1440
+  @A1441
+  @A1442
+  @A1443
+  @A1444
+  @A1445
+  @A1446
+  @A1447
+  @A1448
+  @A1449
+  @A1450
+  @A1451
+  @A1452
+  @A1453
+  @A1454
+  @A1455
+  @A1456
+  @A1457
+  @A1458
+  @A1459
+  @A1460
+  @A1461
+  @A1462
+  @A1463
+  @A1464
+  @A1465
+  @A1466
+  @A1467
+  @A1468
+  @A1469
+  @A1470
+  @A1471
+  @A1472
+  @A1473
+  @A1474
+  @A1475
+  @A1476
+  @A1477
+  @A1478
+  @A1479
+  @A1480
+  @A1481
+  @A1482
+  @A1483
+  @A1484
+  @A1485
+  @A1486
+  @A1487
+  @A1488
+  @A1489
+  @A1490
+  @A1491
+  @A1492
+  @A1493
+  @A1494
+  @A1495
+  @A1496
+  @A1497
+  @A1498
+  @A1499
+  @A1500
+  @A1501
+  @A1502
+  @A1503
+  @A1504
+  @A1505
+  @A1506
+  @A1507
+  @A1508
+  @A1509
+  @A1510
+  @A1511
+  @A1512
+  @A1513
+  @A1514
+  @A1515
+  @A1516
+  @A1517
+  @A1518
+  @A1519
+  @A1520
+  @A1521
+  @A1522
+  @A1523
+  @A1524
+  @A1525
+  @A1526
+  @A1527
+  @A1528
+  @A1529
+  @A1530
+  @A1531
+  @A1532
+  @A1533
+  @A1534
+  @A1535
+  @A1536
+  @A1537
+  @A1538
+  @A1539
+  @A1540
+  @A1541
+  @A1542
+  @A1543
+  @A1544
+  @A1545
+  @A1546
+  @A1547
+  @A1548
+  @A1549
+  @A1550
+  @A1551
+  @A1552
+  @A1553
+  @A1554
+  @A1555
+  @A1556
+  @A1557
+  @A1558
+  @A1559
+  @A1560
+  @A1561
+  @A1562
+  @A1563
+  @A1564
+  @A1565
+  @A1566
+  @A1567
+  @A1568
+  @A1569
+  @A1570
+  @A1571
+  @A1572
+  @A1573
+  @A1574
+  @A1575
+  @A1576
+  @A1577
+  @A1578
+  @A1579
+  @A1580
+  @A1581
+  @A1582
+  @A1583
+  @A1584
+  @A1585
+  @A1586
+  @A1587
+  @A1588
+  @A1589
+  @A1590
+  @A1591
+  @A1592
+  @A1593
+  @A1594
+  @A1595
+  @A1596
+  @A1597
+  @A1598
+  @A1599
+  @A1600
+  @A1601
+  @A1602
+  @A1603
+  @A1604
+  @A1605
+  @A1606
+  @A1607
+  @A1608
+  @A1609
+  @A1610
+  @A1611
+  @A1612
+  @A1613
+  @A1614
+  @A1615
+  @A1616
+  @A1617
+  @A1618
+  @A1619
+  @A1620
+  @A1621
+  @A1622
+  @A1623
+  @A1624
+  @A1625
+  @A1626
+  @A1627
+  @A1628
+  @A1629
+  @A1630
+  @A1631
+  @A1632
+  @A1633
+  @A1634
+  @A1635
+  @A1636
+  @A1637
+  @A1638
+  @A1639
+  @A1640
+  @A1641
+  @A1642
+  @A1643
+  @A1644
+  @A1645
+  @A1646
+  @A1647
+  @A1648
+  @A1649
+  @A1650
+  @A1651
+  @A1652
+  @A1653
+  @A1654
+  @A1655
+  @A1656
+  @A1657
+  @A1658
+  @A1659
+  @A1660
+  @A1661
+  @A1662
+  @A1663
+  @A1664
+  @A1665
+  @A1666
+  @A1667
+  @A1668
+  @A1669
+  @A1670
+  @A1671
+  @A1672
+  @A1673
+  @A1674
+  @A1675
+  @A1676
+  @A1677
+  @A1678
+  @A1679
+  @A1680
+  @A1681
+  @A1682
+  @A1683
+  @A1684
+  @A1685
+  @A1686
+  @A1687
+  @A1688
+  @A1689
+  @A1690
+  @A1691
+  @A1692
+  @A1693
+  @A1694
+  @A1695
+  @A1696
+  @A1697
+  @A1698
+  @A1699
+  @A1700
+  @A1701
+  @A1702
+  @A1703
+  @A1704
+  @A1705
+  @A1706
+  @A1707
+  @A1708
+  @A1709
+  @A1710
+  @A1711
+  @A1712
+  @A1713
+  @A1714
+  @A1715
+  @A1716
+  @A1717
+  @A1718
+  @A1719
+  @A1720
+  @A1721
+  @A1722
+  @A1723
+  @A1724
+  @A1725
+  @A1726
+  @A1727
+  @A1728
+  @A1729
+  @A1730
+  @A1731
+  @A1732
+  @A1733
+  @A1734
+  @A1735
+  @A1736
+  @A1737
+  @A1738
+  @A1739
+  @A1740
+  @A1741
+  @A1742
+  @A1743
+  @A1744
+  @A1745
+  @A1746
+  @A1747
+  @A1748
+  @A1749
+  @A1750
+  @A1751
+  @A1752
+  @A1753
+  @A1754
+  @A1755
+  @A1756
+  @A1757
+  @A1758
+  @A1759
+  @A1760
+  @A1761
+  @A1762
+  @A1763
+  @A1764
+  @A1765
+  @A1766
+  @A1767
+  @A1768
+  @A1769
+  @A1770
+  @A1771
+  @A1772
+  @A1773
+  @A1774
+  @A1775
+  @A1776
+  @A1777
+  @A1778
+  @A1779
+  @A1780
+  @A1781
+  @A1782
+  @A1783
+  @A1784
+  @A1785
+  @A1786
+  @A1787
+  @A1788
+  @A1789
+  @A1790
+  @A1791
+  @A1792
+  @A1793
+  @A1794
+  @A1795
+  @A1796
+  @A1797
+  @A1798
+  @A1799
+  @A1800
+  @A1801
+  @A1802
+  @A1803
+  @A1804
+  @A1805
+  @A1806
+  @A1807
+  @A1808
+  @A1809
+  @A1810
+  @A1811
+  @A1812
+  @A1813
+  @A1814
+  @A1815
+  @A1816
+  @A1817
+  @A1818
+  @A1819
+  @A1820
+  @A1821
+  @A1822
+  @A1823
+  @A1824
+  @A1825
+  @A1826
+  @A1827
+  @A1828
+  @A1829
+  @A1830
+  @A1831
+  @A1832
+  @A1833
+  @A1834
+  @A1835
+  @A1836
+  @A1837
+  @A1838
+  @A1839
+  @A1840
+  @A1841
+  @A1842
+  @A1843
+  @A1844
+  @A1845
+  @A1846
+  @A1847
+  @A1848
+  @A1849
+  @A1850
+  @A1851
+  @A1852
+  @A1853
+  @A1854
+  @A1855
+  @A1856
+  @A1857
+  @A1858
+  @A1859
+  @A1860
+  @A1861
+  @A1862
+  @A1863
+  @A1864
+  @A1865
+  @A1866
+  @A1867
+  @A1868
+  @A1869
+  @A1870
+  @A1871
+  @A1872
+  @A1873
+  @A1874
+  @A1875
+  @A1876
+  @A1877
+  @A1878
+  @A1879
+  @A1880
+  @A1881
+  @A1882
+  @A1883
+  @A1884
+  @A1885
+  @A1886
+  @A1887
+  @A1888
+  @A1889
+  @A1890
+  @A1891
+  @A1892
+  @A1893
+  @A1894
+  @A1895
+  @A1896
+  @A1897
+  @A1898
+  @A1899
+  @A1900
+  @A1901
+  @A1902
+  @A1903
+  @A1904
+  @A1905
+  @A1906
+  @A1907
+  @A1908
+  @A1909
+  @A1910
+  @A1911
+  @A1912
+  @A1913
+  @A1914
+  @A1915
+  @A1916
+  @A1917
+  @A1918
+  @A1919
+  @A1920
+  @A1921
+  @A1922
+  @A1923
+  @A1924
+  @A1925
+  @A1926
+  @A1927
+  @A1928
+  @A1929
+  @A1930
+  @A1931
+  @A1932
+  @A1933
+  @A1934
+  @A1935
+  @A1936
+  @A1937
+  @A1938
+  @A1939
+  @A1940
+  @A1941
+  @A1942
+  @A1943
+  @A1944
+  @A1945
+  @A1946
+  @A1947
+  @A1948
+  @A1949
+  @A1950
+  @A1951
+  @A1952
+  @A1953
+  @A1954
+  @A1955
+  @A1956
+  @A1957
+  @A1958
+  @A1959
+  @A1960
+  @A1961
+  @A1962
+  @A1963
+  @A1964
+  @A1965
+  @A1966
+  @A1967
+  @A1968
+  @A1969
+  @A1970
+  @A1971
+  @A1972
+  @A1973
+  @A1974
+  @A1975
+  @A1976
+  @A1977
+  @A1978
+  @A1979
+  @A1980
+  @A1981
+  @A1982
+  @A1983
+  @A1984
+  @A1985
+  @A1986
+  @A1987
+  @A1988
+  @A1989
+  @A1990
+  @A1991
+  @A1992
+  @A1993
+  @A1994
+  @A1995
+  @A1996
+  @A1997
+  @A1998
+  @A1999
+  @A2000
+  @A2001
+  @A2002
+  @A2003
+  @A2004
+  @A2005
+  @A2006
+  @A2007
+  @A2008
+  @A2009
+  @A2010
+  @A2011
+  @A2012
+  @A2013
+  @A2014
+  @A2015
+  @A2016
+  @A2017
+  @A2018
+  @A2019
+  @A2020
+  @A2021
+  @A2022
+  @A2023
+  @A2024
+  @A2025
+  @A2026
+  @A2027
+  @A2028
+  @A2029
+  @A2030
+  @A2031
+  @A2032
+  @A2033
+  @A2034
+  @A2035
+  @A2036
+  @A2037
+  @A2038
+  @A2039
+  @A2040
+  @A2041
+  @A2042
+  @A2043
+  @A2044
+  @A2045
+  @A2046
+  @A2047
+  @A2048
+  @A2049
+  @A2050
+  @A2051
+  @A2052
+  @A2053
+  @A2054
+  @A2055
+  @A2056
+  @A2057
+  @A2058
+  @A2059
+  @A2060
+  @A2061
+  @A2062
+  @A2063
+  @A2064
+  @A2065
+  @A2066
+  @A2067
+  @A2068
+  @A2069
+  @A2070
+  @A2071
+  @A2072
+  @A2073
+  @A2074
+  @A2075
+  @A2076
+  @A2077
+  @A2078
+  @A2079
+  @A2080
+  @A2081
+  @A2082
+  @A2083
+  @A2084
+  @A2085
+  @A2086
+  @A2087
+  @A2088
+  @A2089
+  @A2090
+  @A2091
+  @A2092
+  @A2093
+  @A2094
+  @A2095
+  @A2096
+  @A2097
+  @A2098
+  @A2099
+  @A2100
+  @A2101
+  @A2102
+  @A2103
+  @A2104
+  @A2105
+  @A2106
+  @A2107
+  @A2108
+  @A2109
+  @A2110
+  @A2111
+  @A2112
+  @A2113
+  @A2114
+  @A2115
+  @A2116
+  @A2117
+  @A2118
+  @A2119
+  @A2120
+  @A2121
+  @A2122
+  @A2123
+  @A2124
+  @A2125
+  @A2126
+  @A2127
+  @A2128
+  @A2129
+  @A2130
+  @A2131
+  @A2132
+  @A2133
+  @A2134
+  @A2135
+  @A2136
+  @A2137
+  @A2138
+  @A2139
+  @A2140
+  @A2141
+  @A2142
+  @A2143
+  @A2144
+  @A2145
+  @A2146
+  @A2147
+  @A2148
+  @A2149
+  @A2150
+  @A2151
+  @A2152
+  @A2153
+  @A2154
+  @A2155
+  @A2156
+  @A2157
+  @A2158
+  @A2159
+  @A2160
+  @A2161
+  @A2162
+  @A2163
+  @A2164
+  @A2165
+  @A2166
+  @A2167
+  @A2168
+  @A2169
+  @A2170
+  @A2171
+  @A2172
+  @A2173
+  @A2174
+  @A2175
+  @A2176
+  @A2177
+  @A2178
+  @A2179
+  @A2180
+  @A2181
+  @A2182
+  @A2183
+  @A2184
+  @A2185
+  @A2186
+  @A2187
+  @A2188
+  @A2189
+  @A2190
+  @A2191
+  @A2192
+  @A2193
+  @A2194
+  @A2195
+  @A2196
+  @A2197
+  @A2198
+  @A2199
+  @A2200
+  @A2201
+  @A2202
+  @A2203
+  @A2204
+  @A2205
+  @A2206
+  @A2207
+  @A2208
+  @A2209
+  @A2210
+  @A2211
+  @A2212
+  @A2213
+  @A2214
+  @A2215
+  @A2216
+  @A2217
+  @A2218
+  @A2219
+  @A2220
+  @A2221
+  @A2222
+  @A2223
+  @A2224
+  @A2225
+  @A2226
+  @A2227
+  @A2228
+  @A2229
+  @A2230
+  @A2231
+  @A2232
+  @A2233
+  @A2234
+  @A2235
+  @A2236
+  @A2237
+  @A2238
+  @A2239
+  @A2240
+  @A2241
+  @A2242
+  @A2243
+  @A2244
+  @A2245
+  @A2246
+  @A2247
+  @A2248
+  @A2249
+  @A2250
+  @A2251
+  @A2252
+  @A2253
+  @A2254
+  @A2255
+  @A2256
+  @A2257
+  @A2258
+  @A2259
+  @A2260
+  @A2261
+  @A2262
+  @A2263
+  @A2264
+  @A2265
+  @A2266
+  @A2267
+  @A2268
+  @A2269
+  @A2270
+  @A2271
+  @A2272
+  @A2273
+  @A2274
+  @A2275
+  @A2276
+  @A2277
+  @A2278
+  @A2279
+  @A2280
+  @A2281
+  @A2282
+  @A2283
+  @A2284
+  @A2285
+  @A2286
+  @A2287
+  @A2288
+  @A2289
+  @A2290
+  @A2291
+  @A2292
+  @A2293
+  @A2294
+  @A2295
+  @A2296
+  @A2297
+  @A2298
+  @A2299
+  @A2300
+  @A2301
+  @A2302
+  @A2303
+  @A2304
+  @A2305
+  @A2306
+  @A2307
+  @A2308
+  @A2309
+  @A2310
+  @A2311
+  @A2312
+  @A2313
+  @A2314
+  @A2315
+  @A2316
+  @A2317
+  @A2318
+  @A2319
+  @A2320
+  @A2321
+  @A2322
+  @A2323
+  @A2324
+  @A2325
+  @A2326
+  @A2327
+  @A2328
+  @A2329
+  @A2330
+  @A2331
+  @A2332
+  @A2333
+  @A2334
+  @A2335
+  @A2336
+  @A2337
+  @A2338
+  @A2339
+  @A2340
+  @A2341
+  @A2342
+  @A2343
+  @A2344
+  @A2345
+  @A2346
+  @A2347
+  @A2348
+  @A2349
+  @A2350
+  @A2351
+  @A2352
+  @A2353
+  @A2354
+  @A2355
+  @A2356
+  @A2357
+  @A2358
+  @A2359
+  @A2360
+  @A2361
+  @A2362
+  @A2363
+  @A2364
+  @A2365
+  @A2366
+  @A2367
+  @A2368
+  @A2369
+  @A2370
+  @A2371
+  @A2372
+  @A2373
+  @A2374
+  @A2375
+  @A2376
+  @A2377
+  @A2378
+  @A2379
+  @A2380
+  @A2381
+  @A2382
+  @A2383
+  @A2384
+  @A2385
+  @A2386
+  @A2387
+  @A2388
+  @A2389
+  @A2390
+  @A2391
+  @A2392
+  @A2393
+  @A2394
+  @A2395
+  @A2396
+  @A2397
+  @A2398
+  @A2399
+  @A2400
+  @A2401
+  @A2402
+  @A2403
+  @A2404
+  @A2405
+  @A2406
+  @A2407
+  @A2408
+  @A2409
+  @A2410
+  @A2411
+  @A2412
+  @A2413
+  @A2414
+  @A2415
+  @A2416
+  @A2417
+  @A2418
+  @A2419
+  @A2420
+  @A2421
+  @A2422
+  @A2423
+  @A2424
+  @A2425
+  @A2426
+  @A2427
+  @A2428
+  @A2429
+  @A2430
+  @A2431
+  @A2432
+  @A2433
+  @A2434
+  @A2435
+  @A2436
+  @A2437
+  @A2438
+  @A2439
+  @A2440
+  @A2441
+  @A2442
+  @A2443
+  @A2444
+  @A2445
+  @A2446
+  @A2447
+  @A2448
+  @A2449
+  @A2450
+  @A2451
+  @A2452
+  @A2453
+  @A2454
+  @A2455
+  @A2456
+  @A2457
+  @A2458
+  @A2459
+  @A2460
+  @A2461
+  @A2462
+  @A2463
+  @A2464
+  @A2465
+  @A2466
+  @A2467
+  @A2468
+  @A2469
+  @A2470
+  @A2471
+  @A2472
+  @A2473
+  @A2474
+  @A2475
+  @A2476
+  @A2477
+  @A2478
+  @A2479
+  @A2480
+  @A2481
+  @A2482
+  @A2483
+  @A2484
+  @A2485
+  @A2486
+  @A2487
+  @A2488
+  @A2489
+  @A2490
+  @A2491
+  @A2492
+  @A2493
+  @A2494
+  @A2495
+  @A2496
+  @A2497
+  @A2498
+  @A2499
+  @A2500
+  @A2501
+  @A2502
+  @A2503
+  @A2504
+  @A2505
+  @A2506
+  @A2507
+  @A2508
+  @A2509
+  @A2510
+  @A2511
+  @A2512
+  @A2513
+  @A2514
+  @A2515
+  @A2516
+  @A2517
+  @A2518
+  @A2519
+  @A2520
+  @A2521
+  @A2522
+  @A2523
+  @A2524
+  @A2525
+  @A2526
+  @A2527
+  @A2528
+  @A2529
+  @A2530
+  @A2531
+  @A2532
+  @A2533
+  @A2534
+  @A2535
+  @A2536
+  @A2537
+  @A2538
+  @A2539
+  @A2540
+  @A2541
+  @A2542
+  @A2543
+  @A2544
+  @A2545
+  @A2546
+  @A2547
+  @A2548
+  @A2549
+  @A2550
+  @A2551
+  @A2552
+  @A2553
+  @A2554
+  @A2555
+  @A2556
+  @A2557
+  @A2558
+  @A2559
+  @A2560
+  @A2561
+  @A2562
+  @A2563
+  @A2564
+  @A2565
+  @A2566
+  @A2567
+  @A2568
+  @A2569
+  @A2570
+  @A2571
+  @A2572
+  @A2573
+  @A2574
+  @A2575
+  @A2576
+  @A2577
+  @A2578
+  @A2579
+  @A2580
+  @A2581
+  @A2582
+  @A2583
+  @A2584
+  @A2585
+  @A2586
+  @A2587
+  @A2588
+  @A2589
+  @A2590
+  @A2591
+  @A2592
+  @A2593
+  @A2594
+  @A2595
+  @A2596
+  @A2597
+  @A2598
+  @A2599
+  @A2600
+  @A2601
+  @A2602
+  @A2603
+  @A2604
+  @A2605
+  @A2606
+  @A2607
+  @A2608
+  @A2609
+  @A2610
+  @A2611
+  @A2612
+  @A2613
+  @A2614
+  @A2615
+  @A2616
+  @A2617
+  @A2618
+  @A2619
+  @A2620
+  @A2621
+  @A2622
+  @A2623
+  @A2624
+  @A2625
+  @A2626
+  @A2627
+  @A2628
+  @A2629
+  @A2630
+  @A2631
+  @A2632
+  @A2633
+  @A2634
+  @A2635
+  @A2636
+  @A2637
+  @A2638
+  @A2639
+  @A2640
+  @A2641
+  @A2642
+  @A2643
+  @A2644
+  @A2645
+  @A2646
+  @A2647
+  @A2648
+  @A2649
+  @A2650
+  @A2651
+  @A2652
+  @A2653
+  @A2654
+  @A2655
+  @A2656
+  @A2657
+  @A2658
+  @A2659
+  @A2660
+  @A2661
+  @A2662
+  @A2663
+  @A2664
+  @A2665
+  @A2666
+  @A2667
+  @A2668
+  @A2669
+  @A2670
+  @A2671
+  @A2672
+  @A2673
+  @A2674
+  @A2675
+  @A2676
+  @A2677
+  @A2678
+  @A2679
+  @A2680
+  @A2681
+  @A2682
+  @A2683
+  @A2684
+  @A2685
+  @A2686
+  @A2687
+  @A2688
+  @A2689
+  @A2690
+  @A2691
+  @A2692
+  @A2693
+  @A2694
+  @A2695
+  @A2696
+  @A2697
+  @A2698
+  @A2699
+  @A2700
+  @A2701
+  @A2702
+  @A2703
+  @A2704
+  @A2705
+  @A2706
+  @A2707
+  @A2708
+  @A2709
+  @A2710
+  @A2711
+  @A2712
+  @A2713
+  @A2714
+  @A2715
+  @A2716
+  @A2717
+  @A2718
+  @A2719
+  @A2720
+  @A2721
+  @A2722
+  @A2723
+  @A2724
+  @A2725
+  @A2726
+  @A2727
+  @A2728
+  @A2729
+  @A2730
+  @A2731
+  @A2732
+  @A2733
+  @A2734
+  @A2735
+  @A2736
+  @A2737
+  @A2738
+  @A2739
+  @A2740
+  @A2741
+  @A2742
+  @A2743
+  @A2744
+  @A2745
+  @A2746
+  @A2747
+  @A2748
+  @A2749
+  @A2750
+  @A2751
+  @A2752
+  @A2753
+  @A2754
+  @A2755
+  @A2756
+  @A2757
+  @A2758
+  @A2759
+  @A2760
+  @A2761
+  @A2762
+  @A2763
+  @A2764
+  @A2765
+  @A2766
+  @A2767
+  @A2768
+  @A2769
+  @A2770
+  @A2771
+  @A2772
+  @A2773
+  @A2774
+  @A2775
+  @A2776
+  @A2777
+  @A2778
+  @A2779
+  @A2780
+  @A2781
+  @A2782
+  @A2783
+  @A2784
+  @A2785
+  @A2786
+  @A2787
+  @A2788
+  @A2789
+  @A2790
+  @A2791
+  @A2792
+  @A2793
+  @A2794
+  @A2795
+  @A2796
+  @A2797
+  @A2798
+  @A2799
+  @A2800
+  @A2801
+  @A2802
+  @A2803
+  @A2804
+  @A2805
+  @A2806
+  @A2807
+  @A2808
+  @A2809
+  @A2810
+  @A2811
+  @A2812
+  @A2813
+  @A2814
+  @A2815
+  @A2816
+  @A2817
+  @A2818
+  @A2819
+  @A2820
+  @A2821
+  @A2822
+  @A2823
+  @A2824
+  @A2825
+  @A2826
+  @A2827
+  @A2828
+  @A2829
+  @A2830
+  @A2831
+  @A2832
+  @A2833
+  @A2834
+  @A2835
+  @A2836
+  @A2837
+  @A2838
+  @A2839
+  @A2840
+  @A2841
+  @A2842
+  @A2843
+  @A2844
+  @A2845
+  @A2846
+  @A2847
+  @A2848
+  @A2849
+  @A2850
+  @A2851
+  @A2852
+  @A2853
+  @A2854
+  @A2855
+  @A2856
+  @A2857
+  @A2858
+  @A2859
+  @A2860
+  @A2861
+  @A2862
+  @A2863
+  @A2864
+  @A2865
+  @A2866
+  @A2867
+  @A2868
+  @A2869
+  @A2870
+  @A2871
+  @A2872
+  @A2873
+  @A2874
+  @A2875
+  @A2876
+  @A2877
+  @A2878
+  @A2879
+  @A2880
+  @A2881
+  @A2882
+  @A2883
+  @A2884
+  @A2885
+  @A2886
+  @A2887
+  @A2888
+  @A2889
+  @A2890
+  @A2891
+  @A2892
+  @A2893
+  @A2894
+  @A2895
+  @A2896
+  @A2897
+  @A2898
+  @A2899
+  @A2900
+  @A2901
+  @A2902
+  @A2903
+  @A2904
+  @A2905
+  @A2906
+  @A2907
+  @A2908
+  @A2909
+  @A2910
+  @A2911
+  @A2912
+  @A2913
+  @A2914
+  @A2915
+  @A2916
+  @A2917
+  @A2918
+  @A2919
+  @A2920
+  @A2921
+  @A2922
+  @A2923
+  @A2924
+  @A2925
+  @A2926
+  @A2927
+  @A2928
+  @A2929
+  @A2930
+  @A2931
+  @A2932
+  @A2933
+  @A2934
+  @A2935
+  @A2936
+  @A2937
+  @A2938
+  @A2939
+  @A2940
+  @A2941
+  @A2942
+  @A2943
+  @A2944
+  @A2945
+  @A2946
+  @A2947
+  @A2948
+  @A2949
+  @A2950
+  @A2951
+  @A2952
+  @A2953
+  @A2954
+  @A2955
+  @A2956
+  @A2957
+  @A2958
+  @A2959
+  @A2960
+  @A2961
+  @A2962
+  @A2963
+  @A2964
+  @A2965
+  @A2966
+  @A2967
+  @A2968
+  @A2969
+  @A2970
+  @A2971
+  @A2972
+  @A2973
+  @A2974
+  @A2975
+  @A2976
+  @A2977
+  @A2978
+  @A2979
+  @A2980
+  @A2981
+  @A2982
+  @A2983
+  @A2984
+  @A2985
+  @A2986
+  @A2987
+  @A2988
+  @A2989
+  @A2990
+  @A2991
+  @A2992
+  @A2993
+  @A2994
+  @A2995
+  @A2996
+  @A2997
+  @A2998
+  @A2999
+  class A {}
+
+  @Retention(RetentionPolicy.RUNTIME) @interface B0 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B3 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B4 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B5 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B6 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B7 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B8 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B9 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B10 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B11 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B12 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B13 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B14 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B15 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B16 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B17 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B18 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B19 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B20 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B21 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B22 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B23 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B24 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B25 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B26 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B27 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B28 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B29 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B30 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B31 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B32 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B33 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B34 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B35 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B36 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B37 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B38 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B39 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B40 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B41 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B42 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B43 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B44 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B45 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B46 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B47 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B48 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B49 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B50 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B51 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B52 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B53 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B54 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B55 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B56 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B57 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B58 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B59 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B60 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B61 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B62 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B63 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B64 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B65 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B66 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B67 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B68 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B69 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B70 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B71 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B72 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B73 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B74 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B75 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B76 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B77 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B78 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B79 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B80 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B81 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B82 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B83 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B84 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B85 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B86 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B87 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B88 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B89 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B90 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B91 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B92 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B93 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B94 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B95 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B96 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B97 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B98 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B99 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B100 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B101 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B102 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B103 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B104 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B105 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B106 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B107 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B108 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B109 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B110 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B111 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B112 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B113 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B114 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B115 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B116 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B117 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B118 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B119 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B120 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B121 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B122 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B123 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B124 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B125 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B126 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B127 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B128 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B129 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B130 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B131 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B132 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B133 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B134 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B135 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B136 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B137 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B138 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B139 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B140 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B141 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B142 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B143 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B144 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B145 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B146 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B147 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B148 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B149 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B150 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B151 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B152 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B153 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B154 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B155 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B156 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B157 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B158 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B159 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B160 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B161 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B162 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B163 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B164 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B165 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B166 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B167 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B168 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B169 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B170 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B171 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B172 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B173 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B174 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B175 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B176 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B177 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B178 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B179 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B180 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B181 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B182 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B183 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B184 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B185 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B186 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B187 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B188 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B189 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B190 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B191 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B192 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B193 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B194 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B195 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B196 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B197 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B198 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B199 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B200 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B201 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B202 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B203 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B204 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B205 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B206 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B207 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B208 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B209 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B210 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B211 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B212 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B213 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B214 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B215 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B216 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B217 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B218 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B219 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B220 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B221 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B222 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B223 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B224 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B225 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B226 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B227 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B228 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B229 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B230 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B231 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B232 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B233 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B234 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B235 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B236 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B237 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B238 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B239 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B240 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B241 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B242 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B243 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B244 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B245 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B246 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B247 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B248 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B249 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B250 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B251 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B252 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B253 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B254 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B255 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B256 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B257 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B258 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B259 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B260 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B261 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B262 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B263 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B264 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B265 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B266 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B267 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B268 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B269 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B270 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B271 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B272 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B273 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B274 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B275 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B276 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B277 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B278 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B279 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B280 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B281 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B282 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B283 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B284 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B285 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B286 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B287 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B288 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B289 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B290 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B291 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B292 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B293 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B294 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B295 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B296 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B297 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B298 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B299 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B300 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B301 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B302 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B303 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B304 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B305 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B306 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B307 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B308 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B309 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B310 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B311 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B312 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B313 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B314 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B315 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B316 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B317 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B318 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B319 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B320 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B321 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B322 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B323 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B324 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B325 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B326 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B327 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B328 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B329 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B330 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B331 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B332 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B333 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B334 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B335 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B336 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B337 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B338 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B339 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B340 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B341 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B342 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B343 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B344 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B345 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B346 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B347 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B348 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B349 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B350 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B351 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B352 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B353 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B354 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B355 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B356 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B357 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B358 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B359 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B360 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B361 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B362 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B363 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B364 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B365 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B366 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B367 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B368 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B369 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B370 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B371 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B372 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B373 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B374 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B375 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B376 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B377 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B378 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B379 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B380 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B381 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B382 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B383 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B384 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B385 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B386 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B387 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B388 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B389 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B390 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B391 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B392 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B393 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B394 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B395 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B396 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B397 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B398 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B399 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B400 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B401 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B402 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B403 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B404 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B405 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B406 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B407 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B408 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B409 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B410 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B411 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B412 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B413 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B414 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B415 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B416 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B417 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B418 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B419 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B420 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B421 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B422 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B423 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B424 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B425 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B426 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B427 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B428 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B429 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B430 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B431 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B432 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B433 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B434 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B435 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B436 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B437 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B438 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B439 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B440 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B441 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B442 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B443 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B444 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B445 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B446 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B447 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B448 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B449 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B450 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B451 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B452 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B453 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B454 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B455 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B456 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B457 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B458 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B459 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B460 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B461 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B462 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B463 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B464 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B465 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B466 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B467 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B468 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B469 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B470 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B471 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B472 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B473 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B474 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B475 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B476 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B477 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B478 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B479 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B480 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B481 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B482 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B483 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B484 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B485 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B486 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B487 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B488 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B489 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B490 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B491 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B492 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B493 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B494 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B495 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B496 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B497 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B498 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B499 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B500 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B501 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B502 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B503 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B504 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B505 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B506 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B507 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B508 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B509 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B510 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B511 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B512 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B513 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B514 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B515 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B516 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B517 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B518 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B519 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B520 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B521 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B522 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B523 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B524 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B525 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B526 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B527 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B528 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B529 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B530 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B531 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B532 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B533 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B534 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B535 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B536 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B537 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B538 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B539 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B540 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B541 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B542 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B543 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B544 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B545 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B546 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B547 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B548 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B549 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B550 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B551 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B552 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B553 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B554 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B555 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B556 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B557 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B558 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B559 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B560 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B561 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B562 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B563 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B564 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B565 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B566 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B567 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B568 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B569 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B570 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B571 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B572 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B573 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B574 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B575 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B576 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B577 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B578 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B579 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B580 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B581 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B582 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B583 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B584 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B585 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B586 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B587 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B588 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B589 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B590 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B591 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B592 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B593 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B594 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B595 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B596 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B597 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B598 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B599 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B600 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B601 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B602 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B603 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B604 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B605 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B606 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B607 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B608 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B609 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B610 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B611 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B612 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B613 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B614 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B615 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B616 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B617 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B618 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B619 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B620 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B621 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B622 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B623 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B624 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B625 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B626 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B627 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B628 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B629 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B630 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B631 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B632 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B633 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B634 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B635 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B636 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B637 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B638 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B639 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B640 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B641 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B642 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B643 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B644 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B645 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B646 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B647 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B648 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B649 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B650 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B651 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B652 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B653 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B654 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B655 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B656 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B657 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B658 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B659 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B660 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B661 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B662 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B663 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B664 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B665 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B666 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B667 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B668 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B669 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B670 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B671 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B672 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B673 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B674 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B675 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B676 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B677 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B678 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B679 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B680 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B681 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B682 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B683 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B684 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B685 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B686 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B687 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B688 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B689 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B690 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B691 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B692 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B693 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B694 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B695 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B696 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B697 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B698 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B699 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B700 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B701 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B702 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B703 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B704 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B705 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B706 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B707 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B708 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B709 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B710 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B711 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B712 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B713 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B714 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B715 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B716 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B717 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B718 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B719 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B720 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B721 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B722 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B723 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B724 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B725 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B726 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B727 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B728 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B729 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B730 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B731 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B732 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B733 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B734 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B735 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B736 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B737 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B738 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B739 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B740 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B741 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B742 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B743 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B744 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B745 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B746 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B747 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B748 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B749 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B750 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B751 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B752 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B753 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B754 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B755 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B756 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B757 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B758 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B759 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B760 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B761 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B762 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B763 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B764 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B765 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B766 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B767 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B768 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B769 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B770 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B771 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B772 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B773 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B774 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B775 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B776 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B777 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B778 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B779 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B780 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B781 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B782 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B783 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B784 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B785 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B786 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B787 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B788 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B789 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B790 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B791 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B792 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B793 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B794 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B795 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B796 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B797 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B798 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B799 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B800 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B801 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B802 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B803 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B804 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B805 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B806 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B807 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B808 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B809 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B810 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B811 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B812 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B813 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B814 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B815 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B816 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B817 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B818 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B819 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B820 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B821 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B822 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B823 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B824 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B825 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B826 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B827 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B828 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B829 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B830 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B831 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B832 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B833 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B834 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B835 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B836 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B837 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B838 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B839 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B840 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B841 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B842 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B843 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B844 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B845 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B846 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B847 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B848 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B849 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B850 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B851 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B852 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B853 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B854 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B855 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B856 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B857 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B858 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B859 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B860 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B861 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B862 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B863 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B864 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B865 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B866 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B867 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B868 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B869 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B870 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B871 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B872 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B873 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B874 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B875 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B876 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B877 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B878 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B879 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B880 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B881 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B882 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B883 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B884 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B885 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B886 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B887 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B888 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B889 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B890 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B891 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B892 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B893 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B894 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B895 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B896 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B897 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B898 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B899 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B900 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B901 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B902 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B903 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B904 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B905 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B906 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B907 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B908 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B909 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B910 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B911 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B912 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B913 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B914 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B915 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B916 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B917 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B918 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B919 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B920 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B921 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B922 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B923 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B924 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B925 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B926 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B927 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B928 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B929 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B930 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B931 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B932 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B933 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B934 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B935 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B936 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B937 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B938 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B939 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B940 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B941 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B942 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B943 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B944 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B945 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B946 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B947 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B948 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B949 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B950 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B951 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B952 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B953 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B954 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B955 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B956 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B957 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B958 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B959 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B960 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B961 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B962 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B963 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B964 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B965 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B966 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B967 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B968 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B969 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B970 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B971 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B972 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B973 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B974 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B975 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B976 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B977 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B978 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B979 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B980 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B981 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B982 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B983 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B984 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B985 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B986 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B987 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B988 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B989 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B990 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B991 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B992 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B993 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B994 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B995 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B996 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B997 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B998 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B999 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1000 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1001 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1002 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1003 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1004 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1005 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1006 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1007 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1008 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1009 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1010 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1011 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1012 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1013 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1014 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1015 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1016 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1017 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1018 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1019 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1020 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1021 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1022 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1023 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1024 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1025 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1026 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1027 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1028 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1029 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1030 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1031 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1032 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1033 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1034 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1035 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1036 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1037 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1038 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1039 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1040 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1041 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1042 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1043 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1044 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1045 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1046 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1047 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1048 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1049 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1050 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1051 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1052 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1053 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1054 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1055 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1056 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1057 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1058 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1059 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1060 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1061 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1062 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1063 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1064 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1065 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1066 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1067 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1068 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1069 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1070 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1071 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1072 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1073 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1074 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1075 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1076 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1077 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1078 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1079 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1080 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1081 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1082 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1083 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1084 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1085 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1086 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1087 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1088 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1089 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1090 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1091 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1092 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1093 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1094 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1095 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1096 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1097 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1098 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1099 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1100 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1101 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1102 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1103 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1104 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1105 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1106 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1107 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1108 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1109 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1110 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1111 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1112 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1113 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1114 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1115 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1116 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1117 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1118 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1119 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1120 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1121 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1122 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1123 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1124 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1125 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1126 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1127 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1128 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1129 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1130 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1131 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1132 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1133 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1134 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1135 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1136 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1137 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1138 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1139 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1140 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1141 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1142 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1143 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1144 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1145 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1146 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1147 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1148 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1149 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1150 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1151 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1152 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1153 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1154 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1155 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1156 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1157 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1158 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1159 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1160 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1161 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1162 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1163 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1164 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1165 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1166 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1167 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1168 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1169 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1170 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1171 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1172 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1173 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1174 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1175 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1176 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1177 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1178 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1179 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1180 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1181 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1182 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1183 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1184 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1185 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1186 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1187 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1188 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1189 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1190 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1191 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1192 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1193 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1194 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1195 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1196 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1197 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1198 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1199 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1200 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1201 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1202 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1203 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1204 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1205 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1206 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1207 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1208 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1209 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1210 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1211 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1212 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1213 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1214 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1215 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1216 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1217 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1218 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1219 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1220 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1221 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1222 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1223 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1224 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1225 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1226 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1227 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1228 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1229 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1230 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1231 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1232 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1233 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1234 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1235 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1236 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1237 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1238 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1239 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1240 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1241 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1242 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1243 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1244 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1245 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1246 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1247 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1248 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1249 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1250 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1251 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1252 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1253 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1254 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1255 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1256 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1257 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1258 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1259 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1260 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1261 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1262 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1263 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1264 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1265 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1266 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1267 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1268 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1269 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1270 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1271 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1272 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1273 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1274 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1275 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1276 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1277 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1278 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1279 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1280 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1281 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1282 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1283 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1284 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1285 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1286 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1287 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1288 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1289 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1290 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1291 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1292 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1293 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1294 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1295 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1296 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1297 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1298 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1299 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1300 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1301 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1302 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1303 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1304 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1305 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1306 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1307 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1308 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1309 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1310 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1311 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1312 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1313 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1314 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1315 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1316 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1317 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1318 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1319 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1320 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1321 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1322 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1323 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1324 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1325 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1326 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1327 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1328 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1329 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1330 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1331 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1332 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1333 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1334 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1335 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1336 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1337 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1338 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1339 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1340 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1341 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1342 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1343 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1344 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1345 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1346 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1347 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1348 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1349 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1350 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1351 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1352 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1353 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1354 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1355 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1356 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1357 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1358 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1359 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1360 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1361 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1362 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1363 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1364 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1365 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1366 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1367 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1368 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1369 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1370 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1371 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1372 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1373 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1374 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1375 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1376 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1377 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1378 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1379 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1380 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1381 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1382 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1383 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1384 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1385 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1386 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1387 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1388 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1389 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1390 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1391 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1392 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1393 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1394 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1395 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1396 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1397 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1398 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1399 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1400 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1401 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1402 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1403 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1404 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1405 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1406 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1407 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1408 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1409 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1410 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1411 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1412 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1413 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1414 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1415 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1416 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1417 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1418 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1419 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1420 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1421 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1422 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1423 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1424 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1425 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1426 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1427 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1428 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1429 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1430 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1431 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1432 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1433 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1434 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1435 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1436 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1437 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1438 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1439 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1440 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1441 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1442 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1443 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1444 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1445 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1446 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1447 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1448 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1449 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1450 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1451 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1452 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1453 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1454 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1455 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1456 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1457 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1458 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1459 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1460 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1461 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1462 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1463 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1464 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1465 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1466 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1467 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1468 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1469 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1470 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1471 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1472 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1473 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1474 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1475 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1476 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1477 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1478 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1479 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1480 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1481 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1482 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1483 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1484 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1485 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1486 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1487 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1488 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1489 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1490 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1491 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1492 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1493 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1494 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1495 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1496 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1497 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1498 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1499 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1500 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1501 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1502 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1503 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1504 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1505 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1506 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1507 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1508 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1509 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1510 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1511 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1512 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1513 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1514 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1515 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1516 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1517 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1518 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1519 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1520 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1521 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1522 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1523 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1524 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1525 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1526 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1527 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1528 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1529 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1530 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1531 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1532 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1533 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1534 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1535 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1536 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1537 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1538 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1539 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1540 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1541 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1542 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1543 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1544 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1545 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1546 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1547 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1548 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1549 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1550 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1551 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1552 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1553 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1554 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1555 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1556 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1557 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1558 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1559 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1560 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1561 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1562 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1563 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1564 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1565 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1566 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1567 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1568 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1569 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1570 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1571 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1572 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1573 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1574 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1575 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1576 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1577 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1578 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1579 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1580 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1581 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1582 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1583 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1584 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1585 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1586 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1587 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1588 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1589 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1590 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1591 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1592 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1593 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1594 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1595 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1596 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1597 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1598 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1599 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1600 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1601 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1602 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1603 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1604 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1605 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1606 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1607 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1608 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1609 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1610 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1611 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1612 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1613 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1614 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1615 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1616 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1617 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1618 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1619 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1620 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1621 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1622 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1623 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1624 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1625 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1626 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1627 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1628 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1629 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1630 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1631 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1632 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1633 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1634 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1635 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1636 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1637 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1638 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1639 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1640 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1641 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1642 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1643 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1644 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1645 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1646 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1647 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1648 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1649 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1650 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1651 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1652 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1653 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1654 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1655 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1656 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1657 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1658 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1659 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1660 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1661 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1662 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1663 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1664 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1665 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1666 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1667 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1668 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1669 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1670 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1671 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1672 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1673 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1674 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1675 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1676 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1677 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1678 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1679 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1680 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1681 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1682 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1683 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1684 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1685 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1686 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1687 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1688 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1689 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1690 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1691 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1692 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1693 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1694 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1695 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1696 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1697 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1698 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1699 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1700 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1701 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1702 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1703 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1704 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1705 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1706 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1707 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1708 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1709 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1710 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1711 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1712 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1713 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1714 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1715 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1716 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1717 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1718 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1719 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1720 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1721 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1722 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1723 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1724 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1725 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1726 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1727 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1728 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1729 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1730 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1731 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1732 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1733 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1734 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1735 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1736 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1737 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1738 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1739 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1740 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1741 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1742 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1743 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1744 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1745 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1746 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1747 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1748 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1749 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1750 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1751 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1752 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1753 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1754 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1755 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1756 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1757 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1758 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1759 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1760 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1761 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1762 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1763 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1764 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1765 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1766 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1767 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1768 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1769 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1770 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1771 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1772 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1773 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1774 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1775 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1776 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1777 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1778 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1779 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1780 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1781 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1782 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1783 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1784 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1785 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1786 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1787 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1788 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1789 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1790 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1791 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1792 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1793 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1794 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1795 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1796 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1797 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1798 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1799 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1800 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1801 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1802 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1803 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1804 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1805 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1806 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1807 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1808 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1809 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1810 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1811 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1812 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1813 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1814 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1815 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1816 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1817 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1818 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1819 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1820 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1821 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1822 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1823 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1824 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1825 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1826 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1827 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1828 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1829 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1830 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1831 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1832 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1833 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1834 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1835 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1836 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1837 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1838 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1839 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1840 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1841 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1842 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1843 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1844 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1845 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1846 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1847 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1848 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1849 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1850 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1851 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1852 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1853 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1854 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1855 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1856 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1857 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1858 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1859 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1860 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1861 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1862 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1863 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1864 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1865 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1866 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1867 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1868 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1869 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1870 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1871 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1872 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1873 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1874 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1875 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1876 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1877 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1878 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1879 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1880 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1881 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1882 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1883 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1884 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1885 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1886 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1887 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1888 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1889 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1890 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1891 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1892 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1893 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1894 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1895 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1896 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1897 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1898 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1899 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1900 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1901 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1902 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1903 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1904 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1905 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1906 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1907 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1908 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1909 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1910 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1911 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1912 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1913 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1914 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1915 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1916 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1917 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1918 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1919 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1920 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1921 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1922 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1923 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1924 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1925 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1926 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1927 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1928 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1929 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1930 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1931 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1932 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1933 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1934 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1935 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1936 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1937 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1938 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1939 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1940 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1941 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1942 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1943 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1944 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1945 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1946 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1947 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1948 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1949 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1950 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1951 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1952 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1953 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1954 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1955 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1956 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1957 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1958 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1959 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1960 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1961 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1962 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1963 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1964 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1965 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1966 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1967 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1968 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1969 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1970 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1971 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1972 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1973 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1974 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1975 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1976 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1977 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1978 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1979 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1980 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1981 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1982 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1983 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1984 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1985 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1986 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1987 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1988 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1989 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1990 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1991 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1992 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1993 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1994 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1995 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1996 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1997 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1998 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B1999 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2000 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2001 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2002 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2003 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2004 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2005 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2006 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2007 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2008 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2009 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2010 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2011 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2012 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2013 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2014 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2015 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2016 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2017 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2018 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2019 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2020 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2021 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2022 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2023 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2024 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2025 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2026 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2027 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2028 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2029 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2030 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2031 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2032 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2033 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2034 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2035 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2036 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2037 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2038 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2039 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2040 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2041 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2042 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2043 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2044 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2045 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2046 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2047 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2048 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2049 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2050 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2051 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2052 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2053 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2054 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2055 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2056 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2057 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2058 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2059 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2060 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2061 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2062 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2063 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2064 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2065 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2066 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2067 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2068 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2069 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2070 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2071 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2072 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2073 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2074 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2075 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2076 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2077 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2078 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2079 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2080 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2081 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2082 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2083 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2084 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2085 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2086 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2087 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2088 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2089 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2090 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2091 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2092 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2093 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2094 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2095 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2096 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2097 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2098 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2099 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2100 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2101 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2102 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2103 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2104 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2105 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2106 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2107 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2108 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2109 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2110 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2111 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2112 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2113 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2114 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2115 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2116 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2117 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2118 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2119 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2120 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2121 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2122 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2123 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2124 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2125 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2126 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2127 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2128 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2129 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2130 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2131 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2132 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2133 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2134 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2135 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2136 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2137 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2138 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2139 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2140 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2141 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2142 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2143 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2144 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2145 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2146 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2147 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2148 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2149 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2150 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2151 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2152 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2153 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2154 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2155 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2156 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2157 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2158 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2159 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2160 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2161 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2162 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2163 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2164 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2165 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2166 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2167 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2168 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2169 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2170 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2171 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2172 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2173 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2174 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2175 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2176 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2177 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2178 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2179 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2180 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2181 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2182 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2183 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2184 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2185 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2186 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2187 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2188 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2189 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2190 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2191 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2192 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2193 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2194 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2195 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2196 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2197 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2198 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2199 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2200 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2201 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2202 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2203 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2204 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2205 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2206 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2207 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2208 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2209 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2210 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2211 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2212 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2213 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2214 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2215 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2216 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2217 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2218 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2219 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2220 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2221 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2222 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2223 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2224 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2225 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2226 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2227 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2228 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2229 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2230 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2231 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2232 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2233 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2234 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2235 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2236 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2237 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2238 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2239 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2240 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2241 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2242 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2243 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2244 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2245 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2246 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2247 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2248 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2249 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2250 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2251 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2252 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2253 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2254 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2255 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2256 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2257 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2258 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2259 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2260 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2261 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2262 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2263 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2264 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2265 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2266 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2267 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2268 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2269 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2270 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2271 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2272 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2273 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2274 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2275 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2276 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2277 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2278 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2279 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2280 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2281 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2282 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2283 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2284 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2285 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2286 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2287 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2288 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2289 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2290 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2291 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2292 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2293 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2294 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2295 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2296 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2297 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2298 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2299 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2300 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2301 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2302 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2303 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2304 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2305 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2306 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2307 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2308 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2309 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2310 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2311 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2312 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2313 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2314 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2315 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2316 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2317 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2318 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2319 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2320 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2321 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2322 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2323 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2324 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2325 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2326 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2327 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2328 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2329 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2330 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2331 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2332 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2333 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2334 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2335 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2336 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2337 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2338 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2339 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2340 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2341 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2342 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2343 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2344 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2345 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2346 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2347 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2348 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2349 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2350 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2351 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2352 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2353 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2354 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2355 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2356 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2357 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2358 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2359 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2360 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2361 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2362 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2363 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2364 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2365 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2366 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2367 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2368 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2369 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2370 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2371 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2372 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2373 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2374 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2375 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2376 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2377 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2378 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2379 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2380 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2381 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2382 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2383 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2384 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2385 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2386 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2387 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2388 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2389 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2390 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2391 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2392 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2393 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2394 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2395 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2396 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2397 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2398 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2399 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2400 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2401 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2402 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2403 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2404 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2405 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2406 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2407 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2408 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2409 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2410 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2411 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2412 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2413 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2414 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2415 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2416 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2417 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2418 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2419 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2420 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2421 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2422 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2423 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2424 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2425 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2426 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2427 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2428 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2429 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2430 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2431 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2432 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2433 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2434 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2435 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2436 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2437 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2438 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2439 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2440 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2441 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2442 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2443 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2444 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2445 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2446 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2447 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2448 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2449 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2450 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2451 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2452 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2453 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2454 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2455 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2456 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2457 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2458 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2459 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2460 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2461 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2462 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2463 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2464 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2465 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2466 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2467 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2468 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2469 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2470 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2471 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2472 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2473 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2474 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2475 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2476 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2477 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2478 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2479 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2480 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2481 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2482 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2483 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2484 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2485 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2486 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2487 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2488 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2489 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2490 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2491 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2492 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2493 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2494 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2495 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2496 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2497 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2498 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2499 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2500 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2501 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2502 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2503 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2504 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2505 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2506 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2507 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2508 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2509 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2510 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2511 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2512 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2513 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2514 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2515 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2516 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2517 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2518 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2519 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2520 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2521 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2522 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2523 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2524 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2525 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2526 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2527 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2528 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2529 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2530 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2531 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2532 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2533 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2534 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2535 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2536 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2537 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2538 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2539 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2540 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2541 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2542 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2543 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2544 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2545 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2546 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2547 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2548 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2549 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2550 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2551 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2552 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2553 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2554 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2555 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2556 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2557 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2558 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2559 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2560 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2561 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2562 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2563 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2564 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2565 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2566 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2567 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2568 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2569 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2570 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2571 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2572 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2573 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2574 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2575 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2576 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2577 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2578 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2579 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2580 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2581 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2582 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2583 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2584 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2585 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2586 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2587 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2588 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2589 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2590 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2591 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2592 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2593 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2594 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2595 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2596 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2597 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2598 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2599 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2600 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2601 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2602 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2603 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2604 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2605 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2606 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2607 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2608 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2609 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2610 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2611 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2612 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2613 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2614 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2615 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2616 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2617 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2618 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2619 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2620 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2621 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2622 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2623 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2624 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2625 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2626 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2627 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2628 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2629 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2630 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2631 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2632 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2633 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2634 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2635 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2636 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2637 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2638 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2639 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2640 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2641 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2642 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2643 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2644 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2645 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2646 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2647 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2648 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2649 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2650 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2651 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2652 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2653 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2654 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2655 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2656 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2657 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2658 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2659 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2660 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2661 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2662 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2663 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2664 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2665 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2666 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2667 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2668 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2669 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2670 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2671 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2672 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2673 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2674 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2675 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2676 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2677 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2678 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2679 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2680 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2681 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2682 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2683 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2684 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2685 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2686 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2687 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2688 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2689 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2690 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2691 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2692 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2693 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2694 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2695 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2696 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2697 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2698 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2699 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2700 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2701 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2702 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2703 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2704 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2705 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2706 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2707 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2708 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2709 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2710 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2711 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2712 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2713 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2714 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2715 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2716 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2717 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2718 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2719 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2720 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2721 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2722 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2723 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2724 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2725 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2726 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2727 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2728 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2729 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2730 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2731 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2732 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2733 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2734 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2735 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2736 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2737 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2738 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2739 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2740 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2741 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2742 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2743 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2744 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2745 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2746 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2747 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2748 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2749 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2750 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2751 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2752 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2753 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2754 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2755 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2756 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2757 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2758 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2759 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2760 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2761 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2762 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2763 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2764 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2765 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2766 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2767 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2768 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2769 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2770 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2771 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2772 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2773 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2774 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2775 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2776 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2777 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2778 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2779 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2780 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2781 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2782 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2783 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2784 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2785 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2786 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2787 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2788 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2789 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2790 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2791 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2792 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2793 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2794 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2795 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2796 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2797 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2798 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2799 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2800 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2801 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2802 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2803 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2804 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2805 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2806 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2807 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2808 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2809 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2810 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2811 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2812 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2813 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2814 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2815 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2816 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2817 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2818 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2819 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2820 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2821 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2822 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2823 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2824 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2825 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2826 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2827 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2828 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2829 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2830 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2831 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2832 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2833 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2834 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2835 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2836 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2837 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2838 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2839 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2840 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2841 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2842 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2843 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2844 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2845 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2846 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2847 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2848 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2849 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2850 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2851 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2852 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2853 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2854 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2855 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2856 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2857 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2858 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2859 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2860 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2861 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2862 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2863 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2864 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2865 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2866 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2867 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2868 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2869 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2870 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2871 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2872 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2873 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2874 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2875 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2876 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2877 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2878 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2879 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2880 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2881 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2882 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2883 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2884 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2885 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2886 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2887 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2888 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2889 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2890 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2891 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2892 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2893 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2894 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2895 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2896 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2897 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2898 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2899 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2900 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2901 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2902 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2903 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2904 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2905 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2906 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2907 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2908 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2909 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2910 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2911 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2912 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2913 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2914 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2915 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2916 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2917 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2918 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2919 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2920 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2921 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2922 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2923 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2924 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2925 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2926 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2927 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2928 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2929 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2930 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2931 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2932 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2933 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2934 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2935 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2936 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2937 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2938 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2939 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2940 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2941 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2942 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2943 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2944 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2945 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2946 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2947 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2948 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2949 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2950 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2951 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2952 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2953 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2954 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2955 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2956 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2957 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2958 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2959 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2960 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2961 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2962 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2963 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2964 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2965 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2966 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2967 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2968 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2969 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2970 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2971 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2972 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2973 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2974 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2975 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2976 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2977 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2978 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2979 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2980 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2981 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2982 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2983 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2984 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2985 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2986 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2987 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2988 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2989 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2990 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2991 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2992 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2993 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2994 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2995 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2996 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2997 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2998 {}
+  @Retention(RetentionPolicy.RUNTIME) @interface B2999 {}
+
+  @B0
+  @B1
+  @B2
+  @B3
+  @B4
+  @B5
+  @B6
+  @B7
+  @B8
+  @B9
+  @B10
+  @B11
+  @B12
+  @B13
+  @B14
+  @B15
+  @B16
+  @B17
+  @B18
+  @B19
+  @B20
+  @B21
+  @B22
+  @B23
+  @B24
+  @B25
+  @B26
+  @B27
+  @B28
+  @B29
+  @B30
+  @B31
+  @B32
+  @B33
+  @B34
+  @B35
+  @B36
+  @B37
+  @B38
+  @B39
+  @B40
+  @B41
+  @B42
+  @B43
+  @B44
+  @B45
+  @B46
+  @B47
+  @B48
+  @B49
+  @B50
+  @B51
+  @B52
+  @B53
+  @B54
+  @B55
+  @B56
+  @B57
+  @B58
+  @B59
+  @B60
+  @B61
+  @B62
+  @B63
+  @B64
+  @B65
+  @B66
+  @B67
+  @B68
+  @B69
+  @B70
+  @B71
+  @B72
+  @B73
+  @B74
+  @B75
+  @B76
+  @B77
+  @B78
+  @B79
+  @B80
+  @B81
+  @B82
+  @B83
+  @B84
+  @B85
+  @B86
+  @B87
+  @B88
+  @B89
+  @B90
+  @B91
+  @B92
+  @B93
+  @B94
+  @B95
+  @B96
+  @B97
+  @B98
+  @B99
+  @B100
+  @B101
+  @B102
+  @B103
+  @B104
+  @B105
+  @B106
+  @B107
+  @B108
+  @B109
+  @B110
+  @B111
+  @B112
+  @B113
+  @B114
+  @B115
+  @B116
+  @B117
+  @B118
+  @B119
+  @B120
+  @B121
+  @B122
+  @B123
+  @B124
+  @B125
+  @B126
+  @B127
+  @B128
+  @B129
+  @B130
+  @B131
+  @B132
+  @B133
+  @B134
+  @B135
+  @B136
+  @B137
+  @B138
+  @B139
+  @B140
+  @B141
+  @B142
+  @B143
+  @B144
+  @B145
+  @B146
+  @B147
+  @B148
+  @B149
+  @B150
+  @B151
+  @B152
+  @B153
+  @B154
+  @B155
+  @B156
+  @B157
+  @B158
+  @B159
+  @B160
+  @B161
+  @B162
+  @B163
+  @B164
+  @B165
+  @B166
+  @B167
+  @B168
+  @B169
+  @B170
+  @B171
+  @B172
+  @B173
+  @B174
+  @B175
+  @B176
+  @B177
+  @B178
+  @B179
+  @B180
+  @B181
+  @B182
+  @B183
+  @B184
+  @B185
+  @B186
+  @B187
+  @B188
+  @B189
+  @B190
+  @B191
+  @B192
+  @B193
+  @B194
+  @B195
+  @B196
+  @B197
+  @B198
+  @B199
+  @B200
+  @B201
+  @B202
+  @B203
+  @B204
+  @B205
+  @B206
+  @B207
+  @B208
+  @B209
+  @B210
+  @B211
+  @B212
+  @B213
+  @B214
+  @B215
+  @B216
+  @B217
+  @B218
+  @B219
+  @B220
+  @B221
+  @B222
+  @B223
+  @B224
+  @B225
+  @B226
+  @B227
+  @B228
+  @B229
+  @B230
+  @B231
+  @B232
+  @B233
+  @B234
+  @B235
+  @B236
+  @B237
+  @B238
+  @B239
+  @B240
+  @B241
+  @B242
+  @B243
+  @B244
+  @B245
+  @B246
+  @B247
+  @B248
+  @B249
+  @B250
+  @B251
+  @B252
+  @B253
+  @B254
+  @B255
+  @B256
+  @B257
+  @B258
+  @B259
+  @B260
+  @B261
+  @B262
+  @B263
+  @B264
+  @B265
+  @B266
+  @B267
+  @B268
+  @B269
+  @B270
+  @B271
+  @B272
+  @B273
+  @B274
+  @B275
+  @B276
+  @B277
+  @B278
+  @B279
+  @B280
+  @B281
+  @B282
+  @B283
+  @B284
+  @B285
+  @B286
+  @B287
+  @B288
+  @B289
+  @B290
+  @B291
+  @B292
+  @B293
+  @B294
+  @B295
+  @B296
+  @B297
+  @B298
+  @B299
+  @B300
+  @B301
+  @B302
+  @B303
+  @B304
+  @B305
+  @B306
+  @B307
+  @B308
+  @B309
+  @B310
+  @B311
+  @B312
+  @B313
+  @B314
+  @B315
+  @B316
+  @B317
+  @B318
+  @B319
+  @B320
+  @B321
+  @B322
+  @B323
+  @B324
+  @B325
+  @B326
+  @B327
+  @B328
+  @B329
+  @B330
+  @B331
+  @B332
+  @B333
+  @B334
+  @B335
+  @B336
+  @B337
+  @B338
+  @B339
+  @B340
+  @B341
+  @B342
+  @B343
+  @B344
+  @B345
+  @B346
+  @B347
+  @B348
+  @B349
+  @B350
+  @B351
+  @B352
+  @B353
+  @B354
+  @B355
+  @B356
+  @B357
+  @B358
+  @B359
+  @B360
+  @B361
+  @B362
+  @B363
+  @B364
+  @B365
+  @B366
+  @B367
+  @B368
+  @B369
+  @B370
+  @B371
+  @B372
+  @B373
+  @B374
+  @B375
+  @B376
+  @B377
+  @B378
+  @B379
+  @B380
+  @B381
+  @B382
+  @B383
+  @B384
+  @B385
+  @B386
+  @B387
+  @B388
+  @B389
+  @B390
+  @B391
+  @B392
+  @B393
+  @B394
+  @B395
+  @B396
+  @B397
+  @B398
+  @B399
+  @B400
+  @B401
+  @B402
+  @B403
+  @B404
+  @B405
+  @B406
+  @B407
+  @B408
+  @B409
+  @B410
+  @B411
+  @B412
+  @B413
+  @B414
+  @B415
+  @B416
+  @B417
+  @B418
+  @B419
+  @B420
+  @B421
+  @B422
+  @B423
+  @B424
+  @B425
+  @B426
+  @B427
+  @B428
+  @B429
+  @B430
+  @B431
+  @B432
+  @B433
+  @B434
+  @B435
+  @B436
+  @B437
+  @B438
+  @B439
+  @B440
+  @B441
+  @B442
+  @B443
+  @B444
+  @B445
+  @B446
+  @B447
+  @B448
+  @B449
+  @B450
+  @B451
+  @B452
+  @B453
+  @B454
+  @B455
+  @B456
+  @B457
+  @B458
+  @B459
+  @B460
+  @B461
+  @B462
+  @B463
+  @B464
+  @B465
+  @B466
+  @B467
+  @B468
+  @B469
+  @B470
+  @B471
+  @B472
+  @B473
+  @B474
+  @B475
+  @B476
+  @B477
+  @B478
+  @B479
+  @B480
+  @B481
+  @B482
+  @B483
+  @B484
+  @B485
+  @B486
+  @B487
+  @B488
+  @B489
+  @B490
+  @B491
+  @B492
+  @B493
+  @B494
+  @B495
+  @B496
+  @B497
+  @B498
+  @B499
+  @B500
+  @B501
+  @B502
+  @B503
+  @B504
+  @B505
+  @B506
+  @B507
+  @B508
+  @B509
+  @B510
+  @B511
+  @B512
+  @B513
+  @B514
+  @B515
+  @B516
+  @B517
+  @B518
+  @B519
+  @B520
+  @B521
+  @B522
+  @B523
+  @B524
+  @B525
+  @B526
+  @B527
+  @B528
+  @B529
+  @B530
+  @B531
+  @B532
+  @B533
+  @B534
+  @B535
+  @B536
+  @B537
+  @B538
+  @B539
+  @B540
+  @B541
+  @B542
+  @B543
+  @B544
+  @B545
+  @B546
+  @B547
+  @B548
+  @B549
+  @B550
+  @B551
+  @B552
+  @B553
+  @B554
+  @B555
+  @B556
+  @B557
+  @B558
+  @B559
+  @B560
+  @B561
+  @B562
+  @B563
+  @B564
+  @B565
+  @B566
+  @B567
+  @B568
+  @B569
+  @B570
+  @B571
+  @B572
+  @B573
+  @B574
+  @B575
+  @B576
+  @B577
+  @B578
+  @B579
+  @B580
+  @B581
+  @B582
+  @B583
+  @B584
+  @B585
+  @B586
+  @B587
+  @B588
+  @B589
+  @B590
+  @B591
+  @B592
+  @B593
+  @B594
+  @B595
+  @B596
+  @B597
+  @B598
+  @B599
+  @B600
+  @B601
+  @B602
+  @B603
+  @B604
+  @B605
+  @B606
+  @B607
+  @B608
+  @B609
+  @B610
+  @B611
+  @B612
+  @B613
+  @B614
+  @B615
+  @B616
+  @B617
+  @B618
+  @B619
+  @B620
+  @B621
+  @B622
+  @B623
+  @B624
+  @B625
+  @B626
+  @B627
+  @B628
+  @B629
+  @B630
+  @B631
+  @B632
+  @B633
+  @B634
+  @B635
+  @B636
+  @B637
+  @B638
+  @B639
+  @B640
+  @B641
+  @B642
+  @B643
+  @B644
+  @B645
+  @B646
+  @B647
+  @B648
+  @B649
+  @B650
+  @B651
+  @B652
+  @B653
+  @B654
+  @B655
+  @B656
+  @B657
+  @B658
+  @B659
+  @B660
+  @B661
+  @B662
+  @B663
+  @B664
+  @B665
+  @B666
+  @B667
+  @B668
+  @B669
+  @B670
+  @B671
+  @B672
+  @B673
+  @B674
+  @B675
+  @B676
+  @B677
+  @B678
+  @B679
+  @B680
+  @B681
+  @B682
+  @B683
+  @B684
+  @B685
+  @B686
+  @B687
+  @B688
+  @B689
+  @B690
+  @B691
+  @B692
+  @B693
+  @B694
+  @B695
+  @B696
+  @B697
+  @B698
+  @B699
+  @B700
+  @B701
+  @B702
+  @B703
+  @B704
+  @B705
+  @B706
+  @B707
+  @B708
+  @B709
+  @B710
+  @B711
+  @B712
+  @B713
+  @B714
+  @B715
+  @B716
+  @B717
+  @B718
+  @B719
+  @B720
+  @B721
+  @B722
+  @B723
+  @B724
+  @B725
+  @B726
+  @B727
+  @B728
+  @B729
+  @B730
+  @B731
+  @B732
+  @B733
+  @B734
+  @B735
+  @B736
+  @B737
+  @B738
+  @B739
+  @B740
+  @B741
+  @B742
+  @B743
+  @B744
+  @B745
+  @B746
+  @B747
+  @B748
+  @B749
+  @B750
+  @B751
+  @B752
+  @B753
+  @B754
+  @B755
+  @B756
+  @B757
+  @B758
+  @B759
+  @B760
+  @B761
+  @B762
+  @B763
+  @B764
+  @B765
+  @B766
+  @B767
+  @B768
+  @B769
+  @B770
+  @B771
+  @B772
+  @B773
+  @B774
+  @B775
+  @B776
+  @B777
+  @B778
+  @B779
+  @B780
+  @B781
+  @B782
+  @B783
+  @B784
+  @B785
+  @B786
+  @B787
+  @B788
+  @B789
+  @B790
+  @B791
+  @B792
+  @B793
+  @B794
+  @B795
+  @B796
+  @B797
+  @B798
+  @B799
+  @B800
+  @B801
+  @B802
+  @B803
+  @B804
+  @B805
+  @B806
+  @B807
+  @B808
+  @B809
+  @B810
+  @B811
+  @B812
+  @B813
+  @B814
+  @B815
+  @B816
+  @B817
+  @B818
+  @B819
+  @B820
+  @B821
+  @B822
+  @B823
+  @B824
+  @B825
+  @B826
+  @B827
+  @B828
+  @B829
+  @B830
+  @B831
+  @B832
+  @B833
+  @B834
+  @B835
+  @B836
+  @B837
+  @B838
+  @B839
+  @B840
+  @B841
+  @B842
+  @B843
+  @B844
+  @B845
+  @B846
+  @B847
+  @B848
+  @B849
+  @B850
+  @B851
+  @B852
+  @B853
+  @B854
+  @B855
+  @B856
+  @B857
+  @B858
+  @B859
+  @B860
+  @B861
+  @B862
+  @B863
+  @B864
+  @B865
+  @B866
+  @B867
+  @B868
+  @B869
+  @B870
+  @B871
+  @B872
+  @B873
+  @B874
+  @B875
+  @B876
+  @B877
+  @B878
+  @B879
+  @B880
+  @B881
+  @B882
+  @B883
+  @B884
+  @B885
+  @B886
+  @B887
+  @B888
+  @B889
+  @B890
+  @B891
+  @B892
+  @B893
+  @B894
+  @B895
+  @B896
+  @B897
+  @B898
+  @B899
+  @B900
+  @B901
+  @B902
+  @B903
+  @B904
+  @B905
+  @B906
+  @B907
+  @B908
+  @B909
+  @B910
+  @B911
+  @B912
+  @B913
+  @B914
+  @B915
+  @B916
+  @B917
+  @B918
+  @B919
+  @B920
+  @B921
+  @B922
+  @B923
+  @B924
+  @B925
+  @B926
+  @B927
+  @B928
+  @B929
+  @B930
+  @B931
+  @B932
+  @B933
+  @B934
+  @B935
+  @B936
+  @B937
+  @B938
+  @B939
+  @B940
+  @B941
+  @B942
+  @B943
+  @B944
+  @B945
+  @B946
+  @B947
+  @B948
+  @B949
+  @B950
+  @B951
+  @B952
+  @B953
+  @B954
+  @B955
+  @B956
+  @B957
+  @B958
+  @B959
+  @B960
+  @B961
+  @B962
+  @B963
+  @B964
+  @B965
+  @B966
+  @B967
+  @B968
+  @B969
+  @B970
+  @B971
+  @B972
+  @B973
+  @B974
+  @B975
+  @B976
+  @B977
+  @B978
+  @B979
+  @B980
+  @B981
+  @B982
+  @B983
+  @B984
+  @B985
+  @B986
+  @B987
+  @B988
+  @B989
+  @B990
+  @B991
+  @B992
+  @B993
+  @B994
+  @B995
+  @B996
+  @B997
+  @B998
+  @B999
+  @B1000
+  @B1001
+  @B1002
+  @B1003
+  @B1004
+  @B1005
+  @B1006
+  @B1007
+  @B1008
+  @B1009
+  @B1010
+  @B1011
+  @B1012
+  @B1013
+  @B1014
+  @B1015
+  @B1016
+  @B1017
+  @B1018
+  @B1019
+  @B1020
+  @B1021
+  @B1022
+  @B1023
+  @B1024
+  @B1025
+  @B1026
+  @B1027
+  @B1028
+  @B1029
+  @B1030
+  @B1031
+  @B1032
+  @B1033
+  @B1034
+  @B1035
+  @B1036
+  @B1037
+  @B1038
+  @B1039
+  @B1040
+  @B1041
+  @B1042
+  @B1043
+  @B1044
+  @B1045
+  @B1046
+  @B1047
+  @B1048
+  @B1049
+  @B1050
+  @B1051
+  @B1052
+  @B1053
+  @B1054
+  @B1055
+  @B1056
+  @B1057
+  @B1058
+  @B1059
+  @B1060
+  @B1061
+  @B1062
+  @B1063
+  @B1064
+  @B1065
+  @B1066
+  @B1067
+  @B1068
+  @B1069
+  @B1070
+  @B1071
+  @B1072
+  @B1073
+  @B1074
+  @B1075
+  @B1076
+  @B1077
+  @B1078
+  @B1079
+  @B1080
+  @B1081
+  @B1082
+  @B1083
+  @B1084
+  @B1085
+  @B1086
+  @B1087
+  @B1088
+  @B1089
+  @B1090
+  @B1091
+  @B1092
+  @B1093
+  @B1094
+  @B1095
+  @B1096
+  @B1097
+  @B1098
+  @B1099
+  @B1100
+  @B1101
+  @B1102
+  @B1103
+  @B1104
+  @B1105
+  @B1106
+  @B1107
+  @B1108
+  @B1109
+  @B1110
+  @B1111
+  @B1112
+  @B1113
+  @B1114
+  @B1115
+  @B1116
+  @B1117
+  @B1118
+  @B1119
+  @B1120
+  @B1121
+  @B1122
+  @B1123
+  @B1124
+  @B1125
+  @B1126
+  @B1127
+  @B1128
+  @B1129
+  @B1130
+  @B1131
+  @B1132
+  @B1133
+  @B1134
+  @B1135
+  @B1136
+  @B1137
+  @B1138
+  @B1139
+  @B1140
+  @B1141
+  @B1142
+  @B1143
+  @B1144
+  @B1145
+  @B1146
+  @B1147
+  @B1148
+  @B1149
+  @B1150
+  @B1151
+  @B1152
+  @B1153
+  @B1154
+  @B1155
+  @B1156
+  @B1157
+  @B1158
+  @B1159
+  @B1160
+  @B1161
+  @B1162
+  @B1163
+  @B1164
+  @B1165
+  @B1166
+  @B1167
+  @B1168
+  @B1169
+  @B1170
+  @B1171
+  @B1172
+  @B1173
+  @B1174
+  @B1175
+  @B1176
+  @B1177
+  @B1178
+  @B1179
+  @B1180
+  @B1181
+  @B1182
+  @B1183
+  @B1184
+  @B1185
+  @B1186
+  @B1187
+  @B1188
+  @B1189
+  @B1190
+  @B1191
+  @B1192
+  @B1193
+  @B1194
+  @B1195
+  @B1196
+  @B1197
+  @B1198
+  @B1199
+  @B1200
+  @B1201
+  @B1202
+  @B1203
+  @B1204
+  @B1205
+  @B1206
+  @B1207
+  @B1208
+  @B1209
+  @B1210
+  @B1211
+  @B1212
+  @B1213
+  @B1214
+  @B1215
+  @B1216
+  @B1217
+  @B1218
+  @B1219
+  @B1220
+  @B1221
+  @B1222
+  @B1223
+  @B1224
+  @B1225
+  @B1226
+  @B1227
+  @B1228
+  @B1229
+  @B1230
+  @B1231
+  @B1232
+  @B1233
+  @B1234
+  @B1235
+  @B1236
+  @B1237
+  @B1238
+  @B1239
+  @B1240
+  @B1241
+  @B1242
+  @B1243
+  @B1244
+  @B1245
+  @B1246
+  @B1247
+  @B1248
+  @B1249
+  @B1250
+  @B1251
+  @B1252
+  @B1253
+  @B1254
+  @B1255
+  @B1256
+  @B1257
+  @B1258
+  @B1259
+  @B1260
+  @B1261
+  @B1262
+  @B1263
+  @B1264
+  @B1265
+  @B1266
+  @B1267
+  @B1268
+  @B1269
+  @B1270
+  @B1271
+  @B1272
+  @B1273
+  @B1274
+  @B1275
+  @B1276
+  @B1277
+  @B1278
+  @B1279
+  @B1280
+  @B1281
+  @B1282
+  @B1283
+  @B1284
+  @B1285
+  @B1286
+  @B1287
+  @B1288
+  @B1289
+  @B1290
+  @B1291
+  @B1292
+  @B1293
+  @B1294
+  @B1295
+  @B1296
+  @B1297
+  @B1298
+  @B1299
+  @B1300
+  @B1301
+  @B1302
+  @B1303
+  @B1304
+  @B1305
+  @B1306
+  @B1307
+  @B1308
+  @B1309
+  @B1310
+  @B1311
+  @B1312
+  @B1313
+  @B1314
+  @B1315
+  @B1316
+  @B1317
+  @B1318
+  @B1319
+  @B1320
+  @B1321
+  @B1322
+  @B1323
+  @B1324
+  @B1325
+  @B1326
+  @B1327
+  @B1328
+  @B1329
+  @B1330
+  @B1331
+  @B1332
+  @B1333
+  @B1334
+  @B1335
+  @B1336
+  @B1337
+  @B1338
+  @B1339
+  @B1340
+  @B1341
+  @B1342
+  @B1343
+  @B1344
+  @B1345
+  @B1346
+  @B1347
+  @B1348
+  @B1349
+  @B1350
+  @B1351
+  @B1352
+  @B1353
+  @B1354
+  @B1355
+  @B1356
+  @B1357
+  @B1358
+  @B1359
+  @B1360
+  @B1361
+  @B1362
+  @B1363
+  @B1364
+  @B1365
+  @B1366
+  @B1367
+  @B1368
+  @B1369
+  @B1370
+  @B1371
+  @B1372
+  @B1373
+  @B1374
+  @B1375
+  @B1376
+  @B1377
+  @B1378
+  @B1379
+  @B1380
+  @B1381
+  @B1382
+  @B1383
+  @B1384
+  @B1385
+  @B1386
+  @B1387
+  @B1388
+  @B1389
+  @B1390
+  @B1391
+  @B1392
+  @B1393
+  @B1394
+  @B1395
+  @B1396
+  @B1397
+  @B1398
+  @B1399
+  @B1400
+  @B1401
+  @B1402
+  @B1403
+  @B1404
+  @B1405
+  @B1406
+  @B1407
+  @B1408
+  @B1409
+  @B1410
+  @B1411
+  @B1412
+  @B1413
+  @B1414
+  @B1415
+  @B1416
+  @B1417
+  @B1418
+  @B1419
+  @B1420
+  @B1421
+  @B1422
+  @B1423
+  @B1424
+  @B1425
+  @B1426
+  @B1427
+  @B1428
+  @B1429
+  @B1430
+  @B1431
+  @B1432
+  @B1433
+  @B1434
+  @B1435
+  @B1436
+  @B1437
+  @B1438
+  @B1439
+  @B1440
+  @B1441
+  @B1442
+  @B1443
+  @B1444
+  @B1445
+  @B1446
+  @B1447
+  @B1448
+  @B1449
+  @B1450
+  @B1451
+  @B1452
+  @B1453
+  @B1454
+  @B1455
+  @B1456
+  @B1457
+  @B1458
+  @B1459
+  @B1460
+  @B1461
+  @B1462
+  @B1463
+  @B1464
+  @B1465
+  @B1466
+  @B1467
+  @B1468
+  @B1469
+  @B1470
+  @B1471
+  @B1472
+  @B1473
+  @B1474
+  @B1475
+  @B1476
+  @B1477
+  @B1478
+  @B1479
+  @B1480
+  @B1481
+  @B1482
+  @B1483
+  @B1484
+  @B1485
+  @B1486
+  @B1487
+  @B1488
+  @B1489
+  @B1490
+  @B1491
+  @B1492
+  @B1493
+  @B1494
+  @B1495
+  @B1496
+  @B1497
+  @B1498
+  @B1499
+  @B1500
+  @B1501
+  @B1502
+  @B1503
+  @B1504
+  @B1505
+  @B1506
+  @B1507
+  @B1508
+  @B1509
+  @B1510
+  @B1511
+  @B1512
+  @B1513
+  @B1514
+  @B1515
+  @B1516
+  @B1517
+  @B1518
+  @B1519
+  @B1520
+  @B1521
+  @B1522
+  @B1523
+  @B1524
+  @B1525
+  @B1526
+  @B1527
+  @B1528
+  @B1529
+  @B1530
+  @B1531
+  @B1532
+  @B1533
+  @B1534
+  @B1535
+  @B1536
+  @B1537
+  @B1538
+  @B1539
+  @B1540
+  @B1541
+  @B1542
+  @B1543
+  @B1544
+  @B1545
+  @B1546
+  @B1547
+  @B1548
+  @B1549
+  @B1550
+  @B1551
+  @B1552
+  @B1553
+  @B1554
+  @B1555
+  @B1556
+  @B1557
+  @B1558
+  @B1559
+  @B1560
+  @B1561
+  @B1562
+  @B1563
+  @B1564
+  @B1565
+  @B1566
+  @B1567
+  @B1568
+  @B1569
+  @B1570
+  @B1571
+  @B1572
+  @B1573
+  @B1574
+  @B1575
+  @B1576
+  @B1577
+  @B1578
+  @B1579
+  @B1580
+  @B1581
+  @B1582
+  @B1583
+  @B1584
+  @B1585
+  @B1586
+  @B1587
+  @B1588
+  @B1589
+  @B1590
+  @B1591
+  @B1592
+  @B1593
+  @B1594
+  @B1595
+  @B1596
+  @B1597
+  @B1598
+  @B1599
+  @B1600
+  @B1601
+  @B1602
+  @B1603
+  @B1604
+  @B1605
+  @B1606
+  @B1607
+  @B1608
+  @B1609
+  @B1610
+  @B1611
+  @B1612
+  @B1613
+  @B1614
+  @B1615
+  @B1616
+  @B1617
+  @B1618
+  @B1619
+  @B1620
+  @B1621
+  @B1622
+  @B1623
+  @B1624
+  @B1625
+  @B1626
+  @B1627
+  @B1628
+  @B1629
+  @B1630
+  @B1631
+  @B1632
+  @B1633
+  @B1634
+  @B1635
+  @B1636
+  @B1637
+  @B1638
+  @B1639
+  @B1640
+  @B1641
+  @B1642
+  @B1643
+  @B1644
+  @B1645
+  @B1646
+  @B1647
+  @B1648
+  @B1649
+  @B1650
+  @B1651
+  @B1652
+  @B1653
+  @B1654
+  @B1655
+  @B1656
+  @B1657
+  @B1658
+  @B1659
+  @B1660
+  @B1661
+  @B1662
+  @B1663
+  @B1664
+  @B1665
+  @B1666
+  @B1667
+  @B1668
+  @B1669
+  @B1670
+  @B1671
+  @B1672
+  @B1673
+  @B1674
+  @B1675
+  @B1676
+  @B1677
+  @B1678
+  @B1679
+  @B1680
+  @B1681
+  @B1682
+  @B1683
+  @B1684
+  @B1685
+  @B1686
+  @B1687
+  @B1688
+  @B1689
+  @B1690
+  @B1691
+  @B1692
+  @B1693
+  @B1694
+  @B1695
+  @B1696
+  @B1697
+  @B1698
+  @B1699
+  @B1700
+  @B1701
+  @B1702
+  @B1703
+  @B1704
+  @B1705
+  @B1706
+  @B1707
+  @B1708
+  @B1709
+  @B1710
+  @B1711
+  @B1712
+  @B1713
+  @B1714
+  @B1715
+  @B1716
+  @B1717
+  @B1718
+  @B1719
+  @B1720
+  @B1721
+  @B1722
+  @B1723
+  @B1724
+  @B1725
+  @B1726
+  @B1727
+  @B1728
+  @B1729
+  @B1730
+  @B1731
+  @B1732
+  @B1733
+  @B1734
+  @B1735
+  @B1736
+  @B1737
+  @B1738
+  @B1739
+  @B1740
+  @B1741
+  @B1742
+  @B1743
+  @B1744
+  @B1745
+  @B1746
+  @B1747
+  @B1748
+  @B1749
+  @B1750
+  @B1751
+  @B1752
+  @B1753
+  @B1754
+  @B1755
+  @B1756
+  @B1757
+  @B1758
+  @B1759
+  @B1760
+  @B1761
+  @B1762
+  @B1763
+  @B1764
+  @B1765
+  @B1766
+  @B1767
+  @B1768
+  @B1769
+  @B1770
+  @B1771
+  @B1772
+  @B1773
+  @B1774
+  @B1775
+  @B1776
+  @B1777
+  @B1778
+  @B1779
+  @B1780
+  @B1781
+  @B1782
+  @B1783
+  @B1784
+  @B1785
+  @B1786
+  @B1787
+  @B1788
+  @B1789
+  @B1790
+  @B1791
+  @B1792
+  @B1793
+  @B1794
+  @B1795
+  @B1796
+  @B1797
+  @B1798
+  @B1799
+  @B1800
+  @B1801
+  @B1802
+  @B1803
+  @B1804
+  @B1805
+  @B1806
+  @B1807
+  @B1808
+  @B1809
+  @B1810
+  @B1811
+  @B1812
+  @B1813
+  @B1814
+  @B1815
+  @B1816
+  @B1817
+  @B1818
+  @B1819
+  @B1820
+  @B1821
+  @B1822
+  @B1823
+  @B1824
+  @B1825
+  @B1826
+  @B1827
+  @B1828
+  @B1829
+  @B1830
+  @B1831
+  @B1832
+  @B1833
+  @B1834
+  @B1835
+  @B1836
+  @B1837
+  @B1838
+  @B1839
+  @B1840
+  @B1841
+  @B1842
+  @B1843
+  @B1844
+  @B1845
+  @B1846
+  @B1847
+  @B1848
+  @B1849
+  @B1850
+  @B1851
+  @B1852
+  @B1853
+  @B1854
+  @B1855
+  @B1856
+  @B1857
+  @B1858
+  @B1859
+  @B1860
+  @B1861
+  @B1862
+  @B1863
+  @B1864
+  @B1865
+  @B1866
+  @B1867
+  @B1868
+  @B1869
+  @B1870
+  @B1871
+  @B1872
+  @B1873
+  @B1874
+  @B1875
+  @B1876
+  @B1877
+  @B1878
+  @B1879
+  @B1880
+  @B1881
+  @B1882
+  @B1883
+  @B1884
+  @B1885
+  @B1886
+  @B1887
+  @B1888
+  @B1889
+  @B1890
+  @B1891
+  @B1892
+  @B1893
+  @B1894
+  @B1895
+  @B1896
+  @B1897
+  @B1898
+  @B1899
+  @B1900
+  @B1901
+  @B1902
+  @B1903
+  @B1904
+  @B1905
+  @B1906
+  @B1907
+  @B1908
+  @B1909
+  @B1910
+  @B1911
+  @B1912
+  @B1913
+  @B1914
+  @B1915
+  @B1916
+  @B1917
+  @B1918
+  @B1919
+  @B1920
+  @B1921
+  @B1922
+  @B1923
+  @B1924
+  @B1925
+  @B1926
+  @B1927
+  @B1928
+  @B1929
+  @B1930
+  @B1931
+  @B1932
+  @B1933
+  @B1934
+  @B1935
+  @B1936
+  @B1937
+  @B1938
+  @B1939
+  @B1940
+  @B1941
+  @B1942
+  @B1943
+  @B1944
+  @B1945
+  @B1946
+  @B1947
+  @B1948
+  @B1949
+  @B1950
+  @B1951
+  @B1952
+  @B1953
+  @B1954
+  @B1955
+  @B1956
+  @B1957
+  @B1958
+  @B1959
+  @B1960
+  @B1961
+  @B1962
+  @B1963
+  @B1964
+  @B1965
+  @B1966
+  @B1967
+  @B1968
+  @B1969
+  @B1970
+  @B1971
+  @B1972
+  @B1973
+  @B1974
+  @B1975
+  @B1976
+  @B1977
+  @B1978
+  @B1979
+  @B1980
+  @B1981
+  @B1982
+  @B1983
+  @B1984
+  @B1985
+  @B1986
+  @B1987
+  @B1988
+  @B1989
+  @B1990
+  @B1991
+  @B1992
+  @B1993
+  @B1994
+  @B1995
+  @B1996
+  @B1997
+  @B1998
+  @B1999
+  @B2000
+  @B2001
+  @B2002
+  @B2003
+  @B2004
+  @B2005
+  @B2006
+  @B2007
+  @B2008
+  @B2009
+  @B2010
+  @B2011
+  @B2012
+  @B2013
+  @B2014
+  @B2015
+  @B2016
+  @B2017
+  @B2018
+  @B2019
+  @B2020
+  @B2021
+  @B2022
+  @B2023
+  @B2024
+  @B2025
+  @B2026
+  @B2027
+  @B2028
+  @B2029
+  @B2030
+  @B2031
+  @B2032
+  @B2033
+  @B2034
+  @B2035
+  @B2036
+  @B2037
+  @B2038
+  @B2039
+  @B2040
+  @B2041
+  @B2042
+  @B2043
+  @B2044
+  @B2045
+  @B2046
+  @B2047
+  @B2048
+  @B2049
+  @B2050
+  @B2051
+  @B2052
+  @B2053
+  @B2054
+  @B2055
+  @B2056
+  @B2057
+  @B2058
+  @B2059
+  @B2060
+  @B2061
+  @B2062
+  @B2063
+  @B2064
+  @B2065
+  @B2066
+  @B2067
+  @B2068
+  @B2069
+  @B2070
+  @B2071
+  @B2072
+  @B2073
+  @B2074
+  @B2075
+  @B2076
+  @B2077
+  @B2078
+  @B2079
+  @B2080
+  @B2081
+  @B2082
+  @B2083
+  @B2084
+  @B2085
+  @B2086
+  @B2087
+  @B2088
+  @B2089
+  @B2090
+  @B2091
+  @B2092
+  @B2093
+  @B2094
+  @B2095
+  @B2096
+  @B2097
+  @B2098
+  @B2099
+  @B2100
+  @B2101
+  @B2102
+  @B2103
+  @B2104
+  @B2105
+  @B2106
+  @B2107
+  @B2108
+  @B2109
+  @B2110
+  @B2111
+  @B2112
+  @B2113
+  @B2114
+  @B2115
+  @B2116
+  @B2117
+  @B2118
+  @B2119
+  @B2120
+  @B2121
+  @B2122
+  @B2123
+  @B2124
+  @B2125
+  @B2126
+  @B2127
+  @B2128
+  @B2129
+  @B2130
+  @B2131
+  @B2132
+  @B2133
+  @B2134
+  @B2135
+  @B2136
+  @B2137
+  @B2138
+  @B2139
+  @B2140
+  @B2141
+  @B2142
+  @B2143
+  @B2144
+  @B2145
+  @B2146
+  @B2147
+  @B2148
+  @B2149
+  @B2150
+  @B2151
+  @B2152
+  @B2153
+  @B2154
+  @B2155
+  @B2156
+  @B2157
+  @B2158
+  @B2159
+  @B2160
+  @B2161
+  @B2162
+  @B2163
+  @B2164
+  @B2165
+  @B2166
+  @B2167
+  @B2168
+  @B2169
+  @B2170
+  @B2171
+  @B2172
+  @B2173
+  @B2174
+  @B2175
+  @B2176
+  @B2177
+  @B2178
+  @B2179
+  @B2180
+  @B2181
+  @B2182
+  @B2183
+  @B2184
+  @B2185
+  @B2186
+  @B2187
+  @B2188
+  @B2189
+  @B2190
+  @B2191
+  @B2192
+  @B2193
+  @B2194
+  @B2195
+  @B2196
+  @B2197
+  @B2198
+  @B2199
+  @B2200
+  @B2201
+  @B2202
+  @B2203
+  @B2204
+  @B2205
+  @B2206
+  @B2207
+  @B2208
+  @B2209
+  @B2210
+  @B2211
+  @B2212
+  @B2213
+  @B2214
+  @B2215
+  @B2216
+  @B2217
+  @B2218
+  @B2219
+  @B2220
+  @B2221
+  @B2222
+  @B2223
+  @B2224
+  @B2225
+  @B2226
+  @B2227
+  @B2228
+  @B2229
+  @B2230
+  @B2231
+  @B2232
+  @B2233
+  @B2234
+  @B2235
+  @B2236
+  @B2237
+  @B2238
+  @B2239
+  @B2240
+  @B2241
+  @B2242
+  @B2243
+  @B2244
+  @B2245
+  @B2246
+  @B2247
+  @B2248
+  @B2249
+  @B2250
+  @B2251
+  @B2252
+  @B2253
+  @B2254
+  @B2255
+  @B2256
+  @B2257
+  @B2258
+  @B2259
+  @B2260
+  @B2261
+  @B2262
+  @B2263
+  @B2264
+  @B2265
+  @B2266
+  @B2267
+  @B2268
+  @B2269
+  @B2270
+  @B2271
+  @B2272
+  @B2273
+  @B2274
+  @B2275
+  @B2276
+  @B2277
+  @B2278
+  @B2279
+  @B2280
+  @B2281
+  @B2282
+  @B2283
+  @B2284
+  @B2285
+  @B2286
+  @B2287
+  @B2288
+  @B2289
+  @B2290
+  @B2291
+  @B2292
+  @B2293
+  @B2294
+  @B2295
+  @B2296
+  @B2297
+  @B2298
+  @B2299
+  @B2300
+  @B2301
+  @B2302
+  @B2303
+  @B2304
+  @B2305
+  @B2306
+  @B2307
+  @B2308
+  @B2309
+  @B2310
+  @B2311
+  @B2312
+  @B2313
+  @B2314
+  @B2315
+  @B2316
+  @B2317
+  @B2318
+  @B2319
+  @B2320
+  @B2321
+  @B2322
+  @B2323
+  @B2324
+  @B2325
+  @B2326
+  @B2327
+  @B2328
+  @B2329
+  @B2330
+  @B2331
+  @B2332
+  @B2333
+  @B2334
+  @B2335
+  @B2336
+  @B2337
+  @B2338
+  @B2339
+  @B2340
+  @B2341
+  @B2342
+  @B2343
+  @B2344
+  @B2345
+  @B2346
+  @B2347
+  @B2348
+  @B2349
+  @B2350
+  @B2351
+  @B2352
+  @B2353
+  @B2354
+  @B2355
+  @B2356
+  @B2357
+  @B2358
+  @B2359
+  @B2360
+  @B2361
+  @B2362
+  @B2363
+  @B2364
+  @B2365
+  @B2366
+  @B2367
+  @B2368
+  @B2369
+  @B2370
+  @B2371
+  @B2372
+  @B2373
+  @B2374
+  @B2375
+  @B2376
+  @B2377
+  @B2378
+  @B2379
+  @B2380
+  @B2381
+  @B2382
+  @B2383
+  @B2384
+  @B2385
+  @B2386
+  @B2387
+  @B2388
+  @B2389
+  @B2390
+  @B2391
+  @B2392
+  @B2393
+  @B2394
+  @B2395
+  @B2396
+  @B2397
+  @B2398
+  @B2399
+  @B2400
+  @B2401
+  @B2402
+  @B2403
+  @B2404
+  @B2405
+  @B2406
+  @B2407
+  @B2408
+  @B2409
+  @B2410
+  @B2411
+  @B2412
+  @B2413
+  @B2414
+  @B2415
+  @B2416
+  @B2417
+  @B2418
+  @B2419
+  @B2420
+  @B2421
+  @B2422
+  @B2423
+  @B2424
+  @B2425
+  @B2426
+  @B2427
+  @B2428
+  @B2429
+  @B2430
+  @B2431
+  @B2432
+  @B2433
+  @B2434
+  @B2435
+  @B2436
+  @B2437
+  @B2438
+  @B2439
+  @B2440
+  @B2441
+  @B2442
+  @B2443
+  @B2444
+  @B2445
+  @B2446
+  @B2447
+  @B2448
+  @B2449
+  @B2450
+  @B2451
+  @B2452
+  @B2453
+  @B2454
+  @B2455
+  @B2456
+  @B2457
+  @B2458
+  @B2459
+  @B2460
+  @B2461
+  @B2462
+  @B2463
+  @B2464
+  @B2465
+  @B2466
+  @B2467
+  @B2468
+  @B2469
+  @B2470
+  @B2471
+  @B2472
+  @B2473
+  @B2474
+  @B2475
+  @B2476
+  @B2477
+  @B2478
+  @B2479
+  @B2480
+  @B2481
+  @B2482
+  @B2483
+  @B2484
+  @B2485
+  @B2486
+  @B2487
+  @B2488
+  @B2489
+  @B2490
+  @B2491
+  @B2492
+  @B2493
+  @B2494
+  @B2495
+  @B2496
+  @B2497
+  @B2498
+  @B2499
+  @B2500
+  @B2501
+  @B2502
+  @B2503
+  @B2504
+  @B2505
+  @B2506
+  @B2507
+  @B2508
+  @B2509
+  @B2510
+  @B2511
+  @B2512
+  @B2513
+  @B2514
+  @B2515
+  @B2516
+  @B2517
+  @B2518
+  @B2519
+  @B2520
+  @B2521
+  @B2522
+  @B2523
+  @B2524
+  @B2525
+  @B2526
+  @B2527
+  @B2528
+  @B2529
+  @B2530
+  @B2531
+  @B2532
+  @B2533
+  @B2534
+  @B2535
+  @B2536
+  @B2537
+  @B2538
+  @B2539
+  @B2540
+  @B2541
+  @B2542
+  @B2543
+  @B2544
+  @B2545
+  @B2546
+  @B2547
+  @B2548
+  @B2549
+  @B2550
+  @B2551
+  @B2552
+  @B2553
+  @B2554
+  @B2555
+  @B2556
+  @B2557
+  @B2558
+  @B2559
+  @B2560
+  @B2561
+  @B2562
+  @B2563
+  @B2564
+  @B2565
+  @B2566
+  @B2567
+  @B2568
+  @B2569
+  @B2570
+  @B2571
+  @B2572
+  @B2573
+  @B2574
+  @B2575
+  @B2576
+  @B2577
+  @B2578
+  @B2579
+  @B2580
+  @B2581
+  @B2582
+  @B2583
+  @B2584
+  @B2585
+  @B2586
+  @B2587
+  @B2588
+  @B2589
+  @B2590
+  @B2591
+  @B2592
+  @B2593
+  @B2594
+  @B2595
+  @B2596
+  @B2597
+  @B2598
+  @B2599
+  @B2600
+  @B2601
+  @B2602
+  @B2603
+  @B2604
+  @B2605
+  @B2606
+  @B2607
+  @B2608
+  @B2609
+  @B2610
+  @B2611
+  @B2612
+  @B2613
+  @B2614
+  @B2615
+  @B2616
+  @B2617
+  @B2618
+  @B2619
+  @B2620
+  @B2621
+  @B2622
+  @B2623
+  @B2624
+  @B2625
+  @B2626
+  @B2627
+  @B2628
+  @B2629
+  @B2630
+  @B2631
+  @B2632
+  @B2633
+  @B2634
+  @B2635
+  @B2636
+  @B2637
+  @B2638
+  @B2639
+  @B2640
+  @B2641
+  @B2642
+  @B2643
+  @B2644
+  @B2645
+  @B2646
+  @B2647
+  @B2648
+  @B2649
+  @B2650
+  @B2651
+  @B2652
+  @B2653
+  @B2654
+  @B2655
+  @B2656
+  @B2657
+  @B2658
+  @B2659
+  @B2660
+  @B2661
+  @B2662
+  @B2663
+  @B2664
+  @B2665
+  @B2666
+  @B2667
+  @B2668
+  @B2669
+  @B2670
+  @B2671
+  @B2672
+  @B2673
+  @B2674
+  @B2675
+  @B2676
+  @B2677
+  @B2678
+  @B2679
+  @B2680
+  @B2681
+  @B2682
+  @B2683
+  @B2684
+  @B2685
+  @B2686
+  @B2687
+  @B2688
+  @B2689
+  @B2690
+  @B2691
+  @B2692
+  @B2693
+  @B2694
+  @B2695
+  @B2696
+  @B2697
+  @B2698
+  @B2699
+  @B2700
+  @B2701
+  @B2702
+  @B2703
+  @B2704
+  @B2705
+  @B2706
+  @B2707
+  @B2708
+  @B2709
+  @B2710
+  @B2711
+  @B2712
+  @B2713
+  @B2714
+  @B2715
+  @B2716
+  @B2717
+  @B2718
+  @B2719
+  @B2720
+  @B2721
+  @B2722
+  @B2723
+  @B2724
+  @B2725
+  @B2726
+  @B2727
+  @B2728
+  @B2729
+  @B2730
+  @B2731
+  @B2732
+  @B2733
+  @B2734
+  @B2735
+  @B2736
+  @B2737
+  @B2738
+  @B2739
+  @B2740
+  @B2741
+  @B2742
+  @B2743
+  @B2744
+  @B2745
+  @B2746
+  @B2747
+  @B2748
+  @B2749
+  @B2750
+  @B2751
+  @B2752
+  @B2753
+  @B2754
+  @B2755
+  @B2756
+  @B2757
+  @B2758
+  @B2759
+  @B2760
+  @B2761
+  @B2762
+  @B2763
+  @B2764
+  @B2765
+  @B2766
+  @B2767
+  @B2768
+  @B2769
+  @B2770
+  @B2771
+  @B2772
+  @B2773
+  @B2774
+  @B2775
+  @B2776
+  @B2777
+  @B2778
+  @B2779
+  @B2780
+  @B2781
+  @B2782
+  @B2783
+  @B2784
+  @B2785
+  @B2786
+  @B2787
+  @B2788
+  @B2789
+  @B2790
+  @B2791
+  @B2792
+  @B2793
+  @B2794
+  @B2795
+  @B2796
+  @B2797
+  @B2798
+  @B2799
+  @B2800
+  @B2801
+  @B2802
+  @B2803
+  @B2804
+  @B2805
+  @B2806
+  @B2807
+  @B2808
+  @B2809
+  @B2810
+  @B2811
+  @B2812
+  @B2813
+  @B2814
+  @B2815
+  @B2816
+  @B2817
+  @B2818
+  @B2819
+  @B2820
+  @B2821
+  @B2822
+  @B2823
+  @B2824
+  @B2825
+  @B2826
+  @B2827
+  @B2828
+  @B2829
+  @B2830
+  @B2831
+  @B2832
+  @B2833
+  @B2834
+  @B2835
+  @B2836
+  @B2837
+  @B2838
+  @B2839
+  @B2840
+  @B2841
+  @B2842
+  @B2843
+  @B2844
+  @B2845
+  @B2846
+  @B2847
+  @B2848
+  @B2849
+  @B2850
+  @B2851
+  @B2852
+  @B2853
+  @B2854
+  @B2855
+  @B2856
+  @B2857
+  @B2858
+  @B2859
+  @B2860
+  @B2861
+  @B2862
+  @B2863
+  @B2864
+  @B2865
+  @B2866
+  @B2867
+  @B2868
+  @B2869
+  @B2870
+  @B2871
+  @B2872
+  @B2873
+  @B2874
+  @B2875
+  @B2876
+  @B2877
+  @B2878
+  @B2879
+  @B2880
+  @B2881
+  @B2882
+  @B2883
+  @B2884
+  @B2885
+  @B2886
+  @B2887
+  @B2888
+  @B2889
+  @B2890
+  @B2891
+  @B2892
+  @B2893
+  @B2894
+  @B2895
+  @B2896
+  @B2897
+  @B2898
+  @B2899
+  @B2900
+  @B2901
+  @B2902
+  @B2903
+  @B2904
+  @B2905
+  @B2906
+  @B2907
+  @B2908
+  @B2909
+  @B2910
+  @B2911
+  @B2912
+  @B2913
+  @B2914
+  @B2915
+  @B2916
+  @B2917
+  @B2918
+  @B2919
+  @B2920
+  @B2921
+  @B2922
+  @B2923
+  @B2924
+  @B2925
+  @B2926
+  @B2927
+  @B2928
+  @B2929
+  @B2930
+  @B2931
+  @B2932
+  @B2933
+  @B2934
+  @B2935
+  @B2936
+  @B2937
+  @B2938
+  @B2939
+  @B2940
+  @B2941
+  @B2942
+  @B2943
+  @B2944
+  @B2945
+  @B2946
+  @B2947
+  @B2948
+  @B2949
+  @B2950
+  @B2951
+  @B2952
+  @B2953
+  @B2954
+  @B2955
+  @B2956
+  @B2957
+  @B2958
+  @B2959
+  @B2960
+  @B2961
+  @B2962
+  @B2963
+  @B2964
+  @B2965
+  @B2966
+  @B2967
+  @B2968
+  @B2969
+  @B2970
+  @B2971
+  @B2972
+  @B2973
+  @B2974
+  @B2975
+  @B2976
+  @B2977
+  @B2978
+  @B2979
+  @B2980
+  @B2981
+  @B2982
+  @B2983
+  @B2984
+  @B2985
+  @B2986
+  @B2987
+  @B2988
+  @B2989
+  @B2990
+  @B2991
+  @B2992
+  @B2993
+  @B2994
+  @B2995
+  @B2996
+  @B2997
+  @B2998
+  @B2999
+  class B {}
+}
diff --git a/luni/src/test/java/libcore/java/math/BigDecimalTest.java b/luni/src/test/java/libcore/java/math/BigDecimalTest.java
index e9c2b0c..d307b14 100644
--- a/luni/src/test/java/libcore/java/math/BigDecimalTest.java
+++ b/luni/src/test/java/libcore/java/math/BigDecimalTest.java
@@ -88,4 +88,12 @@
       assertEquals(0, a.subtract(b).signum());
       assertEquals(0, a.compareTo(b));
     }
+
+    // https://code.google.com/p/android/issues/detail?id=54580
+    public void test54580() {
+        BigDecimal a = new BigDecimal("1.200002");
+        assertEquals("1.200002", a.toPlainString());
+        assertEquals("1.20", a.abs(new MathContext(3,RoundingMode.HALF_UP)).toPlainString());
+        assertEquals("1.200002", a.toPlainString());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/math/BigIntegerTest.java b/luni/src/test/java/libcore/java/math/BigIntegerTest.java
index b3cf93f..15a0dad 100644
--- a/luni/src/test/java/libcore/java/math/BigIntegerTest.java
+++ b/luni/src/test/java/libcore/java/math/BigIntegerTest.java
@@ -17,6 +17,7 @@
 package libcore.java.math;
 
 import java.math.BigInteger;
+import java.util.Random;
 
 public class BigIntegerTest extends junit.framework.TestCase {
     // http://code.google.com/p/android/issues/detail?id=18452
@@ -83,4 +84,76 @@
         } catch (NumberFormatException expected) {
         }
     }
+
+    public void test_Constructor_ILjava_util_Random() throws Exception {
+      Random rand = new Random();
+      BigInteger b;
+      for (int rep = 0; rep < 1024; ++rep) { // Manual flakiness protection for random tests.
+        b = new BigInteger(128, rand);
+        assertTrue(b.toString() + " " + b.bitLength(), b.bitLength() <= 128);
+
+        b = new BigInteger(16, rand);
+        assertTrue(b.toString() + " " + b.bitLength(), b.bitLength() <= 16);
+
+        b = new BigInteger(5, rand);
+        assertTrue(b.toString() + " " + b.bitLength(), b.bitLength() <= 5);
+      }
+    }
+
+    public void test_Constructor_IILjava_util_Random() throws Exception {
+      Random rand = new Random();
+      BigInteger b;
+      for (int rep = 0; rep < 1024; ++rep) { // Manual flakiness protection for random tests.
+        b = new BigInteger(128, 100, rand);
+        assertEquals(b.toString(), 128, b.bitLength());
+        assertTrue(b.isProbablePrime(100));
+
+        b = new BigInteger(16, 100, rand);
+        assertEquals(b.toString(), 16, b.bitLength());
+        assertTrue(b.isProbablePrime(100));
+
+        b = new BigInteger(5, 100, rand);
+        assertEquals(b.toString(), 5, b.bitLength());
+        assertTrue(b.isProbablePrime(100));
+      }
+
+      // Two bits is an interesting special case because there's an even 2-bit prime.
+      int[] primes = new int[1024];
+      boolean saw2 = false;
+      boolean saw3 = false;
+      for (int rep = 0; rep < primes.length; ++rep) { // Manual flakiness protection for random tests.
+        b = new BigInteger(2, 100, rand);
+        assertEquals(b.toString(), 2, b.bitLength());
+        assertTrue(b.isProbablePrime(100));
+        primes[rep] = b.intValue();
+      }
+      for (int i = 0; i < primes.length; ++i) {
+        if (primes[i] == 2) {
+          saw2 = true;
+        } else if (primes[i] == 3) {
+          saw3 = true;
+        } else {
+          fail();
+        }
+      }
+      assertTrue(saw2 && saw3);
+    }
+
+    public void test_probablePrime() throws Exception {
+      Random rand = new Random();
+      BigInteger b;
+      for (int rep = 0; rep < 1024; ++rep) { // Manual flakiness protection for random tests.
+        b = BigInteger.probablePrime(128, rand);
+        assertEquals(b.toString(), 128, b.bitLength());
+        assertTrue(b.isProbablePrime(100));
+
+        b = BigInteger.probablePrime(16, rand);
+        assertEquals(b.toString(), 16, b.bitLength());
+        assertTrue(b.isProbablePrime(100));
+
+        b = BigInteger.probablePrime(5, rand);
+        assertEquals(b.toString(), 5, b.bitLength());
+        assertTrue(b.isProbablePrime(100));
+      }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/net/OldAndroidDatagramTest.java b/luni/src/test/java/libcore/java/net/OldAndroidDatagramTest.java
index 8d79027..108fd35 100644
--- a/luni/src/test/java/libcore/java/net/OldAndroidDatagramTest.java
+++ b/luni/src/test/java/libcore/java/net/OldAndroidDatagramTest.java
@@ -20,7 +20,9 @@
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.SocketTimeoutException;
+import java.nio.channels.DatagramChannel;
 import junit.framework.TestCase;
 
 /**
@@ -36,7 +38,7 @@
      */
 
     class Reflector extends Thread {
-        // Helper class for reflecting incoming datagrams. 
+        // Helper class for reflecting incoming datagrams.
         DatagramSocket socket;
 
         boolean alive = true;
@@ -185,4 +187,23 @@
             }
         }
     }
+
+    public void test_54072_DatagramSocket() throws Exception {
+        DatagramSocket s = new DatagramSocket(null);
+        assertTrue(s.getLocalAddress().isAnyLocalAddress());
+        s.bind(new InetSocketAddress(8888));
+        assertTrue(s.getLocalAddress().isAnyLocalAddress());
+        s.close();
+        assertNull(s.getLocalAddress());
+    }
+
+    public void test_54072_DatagramChannel() throws Exception {
+        DatagramChannel ch = DatagramChannel.open();
+        DatagramSocket s = ch.socket();
+        assertTrue(s.getLocalAddress().isAnyLocalAddress());
+        s.bind(new InetSocketAddress(8888));
+        assertTrue(s.getLocalAddress().isAnyLocalAddress());
+        s.close();
+        assertNull(s.getLocalAddress());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 1f2ebf9..d39e39f 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -16,14 +16,11 @@
 
 package libcore.java.net;
 
+import com.android.okhttp.HttpResponseCache;
 import com.google.mockwebserver.MockResponse;
 import com.google.mockwebserver.MockWebServer;
 import com.google.mockwebserver.RecordedRequest;
 import com.google.mockwebserver.SocketPolicy;
-import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END;
-import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_START;
-import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END;
-import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END;
 import dalvik.system.CloseGuard;
 import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
@@ -49,21 +46,15 @@
 import java.net.UnknownHostException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
-import java.util.TimeZone;
 import java.util.UUID;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.zip.GZIPInputStream;
@@ -81,16 +72,21 @@
 import libcore.java.lang.ref.FinalizationTester;
 import libcore.java.security.TestKeyStore;
 import libcore.javax.net.ssl.TestSSLContext;
-import libcore.net.http.HttpResponseCache;
 import tests.net.StuckServer;
 
+import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END;
+import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_START;
+import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END;
+import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END;
+
 public final class URLConnectionTest extends TestCase {
-    private MockWebServer server = new MockWebServer();
+    private MockWebServer server;
     private HttpResponseCache cache;
     private String hostName;
 
     @Override protected void setUp() throws Exception {
         super.setUp();
+        server = new MockWebServer();
         hostName = server.getHostName();
     }
 
@@ -105,7 +101,7 @@
         System.clearProperty("https.proxyPort");
         server.shutdown();
         if (cache != null) {
-            cache.getCache().delete();
+            cache.delete();
         }
         super.tearDown();
     }
@@ -1840,7 +1836,6 @@
     }
 
     public void testGetKeepAlive() throws Exception {
-        MockWebServer server = new MockWebServer();
         server.enqueue(new MockResponse().setBody("ABC"));
         server.play();
 
diff --git a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
index 4fc70c4..ec20c2a 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
@@ -18,6 +18,7 @@
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
+import java.nio.ByteBuffer;
 import java.nio.channels.NoConnectionPendingException;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
@@ -129,16 +130,44 @@
         }
     }
 
-    /**
-     * We previously leaked a file descriptor for each selector instance created.
-     *
-     * http://code.google.com/p/android/issues/detail?id=5993
-     * http://code.google.com/p/android/issues/detail?id=4825
-     */
+    // We previously leaked a file descriptor for each selector instance created.
+    //
+    // http://code.google.com/p/android/issues/detail?id=5993
+    // http://code.google.com/p/android/issues/detail?id=4825
     public void testLeakingPipes() throws IOException {
         for (int i = 0; i < 2000; i++) {
             Selector selector = Selector.open();
             selector.close();
         }
     }
+
+    public void test_57456() throws Exception {
+      Selector selector = Selector.open();
+      ServerSocketChannel ssc = ServerSocketChannel.open();
+
+      try {
+        // Connect.
+        ssc.configureBlocking(false);
+        ssc.socket().bind(null);
+        SocketChannel sc = SocketChannel.open();
+        sc.connect(ssc.socket().getLocalSocketAddress());
+        sc.finishConnect();
+
+        // Switch to non-blocking so we can use a Selector.
+        sc.configureBlocking(false);
+
+        // Have the 'server' write something.
+        ssc.accept().write(ByteBuffer.allocate(128));
+
+        // At this point, the client should be able to read or write immediately.
+        // (It shouldn't be able to connect because it's already connected.)
+        SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+        assertEquals(1, selector.select());
+        assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, key.readyOps());
+        assertEquals(0, selector.select());
+      } finally {
+        selector.close();
+        ssc.close();
+      }
+    }
 }
diff --git a/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
index 3ece306..6ab91ab 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
@@ -16,30 +16,69 @@
 
 package libcore.java.nio.channels;
 
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.Selector;
+import java.nio.channels.SelectionKey;
 import java.nio.channels.SocketChannel;
+import tests.io.MockOs;
+import static libcore.io.OsConstants.*;
 
 public class SocketChannelTest extends junit.framework.TestCase {
-    public void test_read_intoReadOnlyByteArrays() throws Exception {
-        ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer();
-        ServerSocket ss = new ServerSocket(0);
-        ss.setReuseAddress(true);
-        SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
-        try {
-            sc.read(readOnly);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            sc.read(new ByteBuffer[] { readOnly });
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
-        try {
-            sc.read(new ByteBuffer[] { readOnly }, 0, 1);
-            fail();
-        } catch (IllegalArgumentException expected) {
-        }
+  private final MockOs mockOs = new MockOs();
+
+  @Override public void setUp() throws Exception {
+    mockOs.install();
+  }
+
+  @Override protected void tearDown() throws Exception {
+    mockOs.uninstall();
+  }
+
+  public void test_read_intoReadOnlyByteArrays() throws Exception {
+    ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer();
+    ServerSocket ss = new ServerSocket(0);
+    ss.setReuseAddress(true);
+    SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
+    try {
+      sc.read(readOnly);
+      fail();
+    } catch (IllegalArgumentException expected) {
     }
+    try {
+      sc.read(new ByteBuffer[] { readOnly });
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+    try {
+      sc.read(new ByteBuffer[] { readOnly }, 0, 1);
+      fail();
+    } catch (IllegalArgumentException expected) {
+    }
+  }
+
+  public void test_56684() throws Exception {
+    mockOs.enqueueFault("connect", ENETUNREACH);
+
+    SocketChannel sc = SocketChannel.open();
+    sc.configureBlocking(false);
+
+    Selector selector = Selector.open();
+    SelectionKey selectionKey = sc.register(selector, SelectionKey.OP_CONNECT);
+
+    try {
+      sc.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 }), 0));
+      fail();
+    } catch (ConnectException ex) {
+    }
+
+    try {
+      sc.finishConnect();
+    } catch (ClosedChannelException expected) {
+    }
+  }
 }
diff --git a/luni/src/test/java/libcore/java/nio/charset/CharsetEncoderTest.java b/luni/src/test/java/libcore/java/nio/charset/CharsetEncoderTest.java
index d733a9f..ff510e0 100644
--- a/luni/src/test/java/libcore/java/nio/charset/CharsetEncoderTest.java
+++ b/luni/src/test/java/libcore/java/nio/charset/CharsetEncoderTest.java
@@ -86,20 +86,23 @@
         assertEquals(1, cr.length());
     }
 
-    public void testCharsetEncoderSurrogatesBrokenByDesign_IGNORE_RI() throws Exception {
-        testCharsetEncoderSurrogatesBrokenByDesign_RI(CodingErrorAction.IGNORE);
+    public void testCharsetEncoderSplitSurrogates_IGNORE() throws Exception {
+        testCharsetEncoderSplitSurrogates(CodingErrorAction.IGNORE);
     }
 
-    public void testCharsetEncoderSurrogatesBrokenByDesign_REPORT_RI() throws Exception {
-        testCharsetEncoderSurrogatesBrokenByDesign_RI(CodingErrorAction.REPORT);
+    public void testCharsetEncoderSplitSurrogates_REPORT() throws Exception {
+        testCharsetEncoderSplitSurrogates(CodingErrorAction.REPORT);
     }
 
-    public void testCharsetEncoderSurrogatesBrokenByDesign_REPLACE_RI() throws Exception {
-        testCharsetEncoderSurrogatesBrokenByDesign_RI(CodingErrorAction.REPLACE);
+    public void testCharsetEncoderSplitSurrogates_REPLACE() throws Exception {
+        testCharsetEncoderSplitSurrogates(CodingErrorAction.REPLACE);
     }
 
-    private void testCharsetEncoderSurrogatesBrokenByDesign_RI(CodingErrorAction cea) throws Exception {
-        // stupid: on the RI, writing the two halves of the surrogate pair in separate writes
+    private void testCharsetEncoderSplitSurrogates(CodingErrorAction cea) throws Exception {
+        // Writing the two halves of the surrogate pair in separate writes should work just fine.
+        // This is true of Android and ICU, but not of the RI.
+
+        // On the RI, writing the two halves of the surrogate pair in separate writes
         // is an error because the CharsetEncoder doesn't remember it's half-way through a
         // surrogate pair across the two calls!
 
@@ -108,55 +111,8 @@
         // replacement character U+fffd when it sees the second character (because it too
         // doesn't remember seeing the first).
 
-        Charset cs = Charset.forName("UTF-32BE");
-        CharsetEncoder e = cs.newEncoder();
-        e.onMalformedInput(cea);
-        e.onUnmappableCharacter(cea);
-        ByteBuffer bb = ByteBuffer.allocate(128);
-        CoderResult cr = e.encode(CharBuffer.wrap(new char[] { '\ud842' }), bb, false);
-        assertEquals(CoderResult.UNDERFLOW, cr);
-        assertEquals(0, bb.position());
-        cr = e.encode(CharBuffer.wrap(new char[] { '\udf9f' }), bb, false);
-        if (cea == CodingErrorAction.REPORT) {
-            assertTrue(cr.toString(), cr.isMalformed());
-            assertEquals(1, cr.length());
-            return;
-        }
-        assertEquals(CoderResult.UNDERFLOW, cr);
-        int expectedPosition = 0;
-        if (cea == CodingErrorAction.REPLACE) {
-            expectedPosition = 4;
-            assertEquals(expectedPosition, bb.position());
-            System.err.println(Arrays.toString(Arrays.copyOfRange(bb.array(), 0, bb.position())));
-            assertEquals((byte) 0x00, bb.get(0));
-            assertEquals((byte) 0x00, bb.get(1));
-            assertEquals((byte) 0xff, bb.get(2));
-            assertEquals((byte) 0xfd, bb.get(3));
-        }
-        assertEquals(expectedPosition, bb.position());
-        cr = e.encode(CharBuffer.wrap(new char[] { }), bb, true);
-        assertEquals(CoderResult.UNDERFLOW, cr);
-        assertEquals(expectedPosition, bb.position());
-        cr = e.flush(bb);
-        assertEquals(CoderResult.UNDERFLOW, cr);
-        assertEquals(expectedPosition, bb.position());
-    }
+        // Android just does the right thing.
 
-    public void testCharsetEncoderSurrogatesBrokenByDesign_IGNORE() throws Exception {
-        testCharsetEncoderSurrogatesBrokenByDesign(CodingErrorAction.IGNORE);
-    }
-
-    public void testCharsetEncoderSurrogatesBrokenByDesign_REPORT() throws Exception {
-        testCharsetEncoderSurrogatesBrokenByDesign(CodingErrorAction.REPORT);
-    }
-
-    public void testCharsetEncoderSurrogatesBrokenByDesign_REPLACE() throws Exception {
-        testCharsetEncoderSurrogatesBrokenByDesign(CodingErrorAction.REPLACE);
-    }
-
-    private void testCharsetEncoderSurrogatesBrokenByDesign(CodingErrorAction cea) throws Exception {
-        // Writing the two halves of the surrogate pair in separate writes works just fine.
-        // This is true of Android and ICU, but not of the RI.
         Charset cs = Charset.forName("UTF-32BE");
         CharsetEncoder e = cs.newEncoder();
         e.onMalformedInput(cea);
@@ -191,8 +147,9 @@
         assertEquals(4, bb.position());
         try {
             cr = e.flush(bb);
+            fail();
         } catch (IllegalStateException expected) {
-            // you must call encode with endOfInput true before you can flush.
+            // You must call encode with endOfInput true before you can flush.
         }
 
         // We had a bug where we wouldn't reset inEnd before calling encode in implFlush.
diff --git a/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java b/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java
index 24daa52..ddc2b29 100644
--- a/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java
+++ b/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java
@@ -199,17 +199,6 @@
         assertDecodes(cs, "a\u0666", 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
     }
 
-    public void test_preNioAliases() throws Exception {
-        // Various pre-nio java.lang/java.io encoding names are translated to nio charsets.
-        assertEquals("UTF-16BE", Charset.forName("UnicodeBigUnmarked").name());
-        assertEquals("UTF-16LE", Charset.forName("UnicodeLittleUnmarked").name());
-        assertEquals("UTF-16", Charset.forName("Unicode").name());
-        assertEquals("UTF-16", Charset.forName("UnicodeBig").name());
-        assertEquals("x-UTF-16LE-BOM", Charset.forName("UnicodeLittle").name());
-        assertEquals("X-UTF-32BE-BOM", Charset.forName("UTF_32BE_BOM").name());
-        assertEquals("X-UTF-32LE-BOM", Charset.forName("UTF_32LE_BOM").name());
-    }
-
     private byte[] toByteArray(int[] ints) {
         byte[] result = new byte[ints.length];
         for (int i = 0; i < ints.length; ++i) {
diff --git a/luni/src/test/java/libcore/java/nio/charset/Charset_TestGenerator.java b/luni/src/test/java/libcore/java/nio/charset/Charset_TestGenerator.java
index b189382..49c5f23 100644
--- a/luni/src/test/java/libcore/java/nio/charset/Charset_TestGenerator.java
+++ b/luni/src/test/java/libcore/java/nio/charset/Charset_TestGenerator.java
@@ -204,8 +204,7 @@
 
         @Override
         void consume (int code) {
-            System.out.print(code);
-            System.out.print(", ");
+            System.out.printf("0x%x, ", code);
             col++;
             if (col == colMax) {
                 System.out.println();
diff --git a/luni/src/test/java/libcore/java/nio/charset/OldCharset_AbstractTest.java b/luni/src/test/java/libcore/java/nio/charset/OldCharset_AbstractTest.java
index d6a635e..411727e 100644
--- a/luni/src/test/java/libcore/java/nio/charset/OldCharset_AbstractTest.java
+++ b/luni/src/test/java/libcore/java/nio/charset/OldCharset_AbstractTest.java
@@ -43,13 +43,13 @@
     static char[] testChars;
     static byte[] testBytes;
 
-    static char[] theseChars (int[] codes) {
+    static char[] theseChars (int... codes) {
         char[] chars = new char[codes.length];
         for (int i = 0; i < codes.length; i++) chars[i] = (char) codes[i];
         return chars;
     }
 
-    static byte[] theseBytes (int[] codes) {
+    static byte[] theseBytes (int... codes) {
         byte[] bytes = new byte[codes.length];
         for (int i = 0; i < codes.length; i++) bytes[i] = (byte) codes[i];
         return bytes;
@@ -102,7 +102,7 @@
     public void test_dumpEncoded () throws CharacterCodingException {
         if (testChars == null) return;
         if (testChars.length == 0) return;
-        if (testBytes.length > 0) return;
+        if (testBytes != null) return;
         System.out.format("\ntest_dumpEncoded() for name %s => %s (class = %s)\n",
                 charsetName, charset.name(), getClass().getName());
         Charset_TestGenerator.Dumper out = new Charset_TestGenerator.Dumper1();
@@ -122,30 +122,10 @@
 
     static void decode (byte[] input, char[] expectedOutput) throws CharacterCodingException {
         ByteBuffer inputBB = ByteBuffer.wrap(input);
-        CharBuffer outputCB;
         decoder.onMalformedInput(CodingErrorAction.REPORT);
-        outputCB = decoder.decode(inputBB);
+        CharBuffer outputCB = decoder.decode(inputBB);
         outputCB.rewind();
-
-//        assertTrue("Decoded charactes must match!",
-//                Arrays.equals(expectedOutput, outputCB.array()));
-        assertEqualChars("Decoded charactes must match!",
-                expectedOutput, outputCB);
-
-//        assertEqualChars2("Decoded charactes must match!",
-//                expectedOutput,
-//                outputCB.array(),
-//                input);
-//        assertTrue("Decoded charactes (REPLACEed ones INCLUSIVE) must match!",
-//                Arrays.equals(expectedOutput, outputCB.array()));
-
-//        assertEqualChars("Decoded charactes (REPLACEed ones INCLUSIVE) must match!",
-//                expectedOutput,
-//                outputCB.array());
-
-//        assertEquals("Decoded charactes must match!",
-//                String.valueOf(allChars),
-//                outputCB.toString());
+        assertEqualChars(expectedOutput, outputCB);
     }
 
     public void test_Decode () throws CharacterCodingException {
@@ -241,32 +221,16 @@
 //        assertTrue(msg, Arrays.equals(actual, expected));
     }
 
-    static void assertEqualChars (String msg, char[] expected, CharBuffer actualCB) {
-        boolean match = true;
-        boolean lenMatch = true;
-        char actual;
-        int len = actualCB.length();
-        if (expected.length != len) {
-            lenMatch = false;
-            if (expected.length < len) len = expected.length;
-        }
-        for (int i = 0; i < len; i++) {
-            actual = actualCB.get();
+    static void assertEqualChars(char[] expected, CharBuffer actualCB) {
+        assertEquals(expected.length, actualCB.length());
+        for (int i = 0; i < actualCB.length(); ++i) {
+            char actual = actualCB.get();
             if (actual != expected[i]) {
-                String detail = String.format(
-                        "Mismatch at index %d: %d instead of expected %d.\n",
-                        i, (int) actual, (int) expected[i]);
-                match = false;
-                fail(msg + ": " + detail);
+                String detail = String.format("Mismatch at index %d: %d instead of expected %d.\n",
+                                              i, (int) actual, (int) expected[i]);
+                fail(detail);
             }
-//            else {
-//                System.out.format("Match index %d: %d = %d\n",
-//                        i, (int) actual[i], (int) expected[i]);
-//            }
         }
-        assertTrue(msg, match);
-        assertTrue(msg + "(IN LENGTH ALSO!)", lenMatch);
-//        assertTrue(msg, Arrays.equals(actual, expected));
     }
 
     static void assertEqualBytes (String msg, byte[] expected, ByteBuffer actualBB) {
diff --git a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP.java b/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP.java
index 2e7fcc2..4849ad3 100644
--- a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP.java
+++ b/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP.java
@@ -20,506 +20,32 @@
 import java.nio.charset.CharacterCodingException;
 import java.nio.charset.CodingErrorAction;
 
-/** @hide
- * SEE correspondig_Android test class:
- */
-
 public class OldCharset_MultiByte_EUC_JP extends OldCharset_AbstractTest {
+  @Override protected void setUp() throws Exception {
+    charsetName = "EUC-JP";
+    testChars = "東京 とうきょう トウキョウ Tokyo 123".toCharArray();
+    testBytes = theseBytes(0xc5, 0xec, 0xb5, 0xfe, ' ',
+                           0xa4, 0xc8, 0xa4, 0xa6, 0xa4, 0xad, 0xa4, 0xe7, 0xa4, 0xa6, ' ',
+                           0xa5, 0xc8, 0xa5, 0xa6, 0xa5, 0xad, 0xa5, 0xe7, 0xa5, 0xa6, ' ',
+                           'T', 'o', 'k', 'y', 'o', ' ', '1', '2', '3');
+    super.setUp();
+  }
 
-    protected void setUp() throws Exception {
-        charsetName = "EUC-JP";
-
-        testChars = theseChars(new int[]{
-0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
-96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
-161, 162, 163, 164, /*165,*/ 166, 167, 168, 169, 170, 172, 174, 175, 176, 177, 180,
-182, 184, 186, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
-204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
-221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
-237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
-253, 254, 255, 256, 266, 278, 288, 298, 308, 318, 328, 338, 348, 358, 368, 378,
-461, 471, 501, 711, 728, 900, 910, 920, 931, 941, 951, 961, 971, 1025, 1035, 1045,
-1055, 1065, 1075, 1085, 1095, 1105, 1115, 8208, 8220, 8230, 8240, 8251, 8451, 8470, 8482, 8592,
-8658, 8704, 8715, 8730, 8743, 8756, 8786, 8800, 8810, 8834, 8869, 8978, 9472, 9484, 9495, 9507,
-9519, 9531, 9547, 9632, 9650, 9660, 9670, 9711, 9733, 9792, 9834, 12288, 12298, 12308, 12353, 12363,
-12373, 12383, 12393, 12403, 12413, 12423, 12433, 12443, 12453, 12463, 12473, 12483, 12493, 12503, 12513, 12523,
-12533, 19968, 19978, 19988, 19998, 20008, 20018, 20028, 20039, 20049, 20060, 20072, 20083, 20094, 20104, 20114,
-20124, 20134, 20144, 20154, 20164, 20174, 20184, 20194, 20205, 20215, 20225, 20235, 20245, 20270, 20280, 20290,
-20300, 20310, 20320, 20330, 20341, 20351, 20361, 20371, 20381, 20395, 20405, 20415, 20425, 20436, 20447, 20462,
-20472, 20484, 20494, 20504, 20514, 20524, 20534, 20544, 20554, 20565, 20575, 20586, 20596, 20608, 20618, 20628,
-20638, 20650, 20660, 20670, 20681, 20691, 20701, 20711, 20721, 20731, 20742, 20752, 20762, 20775, 20785, 20795,
-20805, 20815, 20826, 20836, 20846, 20856, 20866, 20876, 20886, 20896, 20906, 20916, 20926, 20936, 20946, 20956,
-20966, 20976, 20986, 20996, 21006, 21016, 21026, 21038, 21048, 21059, 21069, 21079, 21089, 21102, 21112, 21122,
-21132, 21142, 21152, 21162, 21172, 21182, 21192, 21202, 21212, 21222, 21232, 21242, 21253, 21263, 21273, 21283,
-21293, 21304, 21314, 21324, 21335, 21345, 21356, 21367, 21378, 21390, 21400, 21412, 21422, 21432, 21442, 21452,
-21462, 21472, 21482, 21493, 21505, 21515, 21530, 21542, 21553, 21563, 21574, 21585, 21598, 21608, 21619, 21629,
-21640, 21650, 21660, 21670, 21681, 21691, 21702, 21720, 21730, 21740, 21750, 21760, 21772, 21782, 21802, 21813,
-21824, 21834, 21846, 21856, 21883, 21894, 21905, 21916, 21927, 21938, 21951, 21961, 21971, 21982, 21993, 22006,
-22021, 22031, 22041, 22057, 22067, 22077, 22089, 22100, 22110, 22120, 22130, 22144, 22154, 22164, 22174, 22184,
-22195, 22206, 22216, 22227, 22237, 22247, 22257, 22269, 22279, 22289, 22299, 22309, 22319, 22331, 22341, 22351,
-22369, 22379, 22389, 22399, 22409, 22419, 22429, 22439, 22451, 22461, 22471, 22482, 22492, 22502, 22512, 22522,
-22532, 22549, 22559, 22570, 22580, 22591, 22601, 22612, 22622, 22632, 22642, 22652, 22663, 22675, 22685, 22696,
-22706, 22716, 22727, 22737, 22748, 22761, 22771, 22781, 22793, 22803, 22813, 22823, 22833, 22846, 22856, 22866,
-22877, 22887, 22898, 22908, 22922, 22933, 22943, 22956, 22967, 22977, 22987, 23001, 23011, 23022, 23035, 23049,
-23059, 23070, 23080, 23093, 23104, 23116, 23130, 23141, 23159, 23179, 23190, 23200, 23212, 23224, 23234, 23244,
-23254, 23264, 23274, 23285, 23296, 23307, 23318, 23329, 23340, 23350, 23360, 23371, 23381, 23391, 23401, 23411,
-23421, 23431, 23441, 23451, 23461, 23471, 23481, 23491, 23501, 23511, 23521, 23531, 23541, 23551, 23561, 23571,
-23582, 23592, 23602, 23612, 23622, 23632, 23642, 23652, 23662, 23673, 23687, 23697, 23709, 23720, 23730, 23740,
-23751, 23762, 23773, 23784, 23794, 23805, 23815, 23825, 23835, 23846, 23857, 23869, 23880, 23890, 23900, 23913,
-23923, 23934, 23944, 23954, 23965, 23975, 23986, 23996, 24007, 24018, 24029, 24039, 24049, 24059, 24070, 24081,
-24091, 24101, 24111, 24125, 24135, 24145, 24155, 24168, 24178, 24188, 24199, 24213, 24224, 24234, 24245, 24255,
-24265, 24275, 24285, 24296, 24307, 24318, 24328, 24339, 24349, 24359, 24369, 24379, 24389, 24400, 24411, 24422,
-24432, 24442, 24452, 24463, 24473, 24484, 24494, 24504, 24515, 24525, 24535, 24545, 24555, 24565, 24575, 24586,
-24596, 24607, 24617, 24627, 24640, 24650, 24660, 24671, 24681, 24693, 24703, 24713, 24723, 24733, 24743, 24753,
-24763, 24773, 24783, 24793, 24803, 24816, 24826, 24838, 24848, 24858, 24871, 24881, 24892, 24902, 24915, 24925,
-24935, 24945, 24955, 24967, 24977, 24988, 24999, 25010, 25020, 25030, 25040, 25052, 25062, 25074, 25084, 25095,
-25105, 25115, 25126, 25136, 25147, 25158, 25168, 25178, 25188, 25198, 25209, 25219, 25229, 25239, 25254, 25265,
-25275, 25285, 25295, 25305, 25322, 25332, 25342, 25352, 25363, 25375, 25385, 25397, 25407, 25417, 25427, 25445,
-25457, 25467, 25479, 25490, 25502, 25512, 25522, 25533, 25544, 25554, 25564, 25577, 25587, 25606, 25616, 25628,
-25638, 25648, 25658, 25675, 25688, 25699, 25709, 25720, 25731, 25743, 25753, 25763, 25773, 25785, 25796, 25806,
-25816, 25826, 25836, 25846, 25856, 25866, 25876, 25886, 25897, 25908, 25918, 25928, 25938, 25949, 25959, 25970,
-25981, 25991, 26001, 26011, 26021, 26031, 26041, 26051, 26062, 26072, 26082, 26092, 26105, 26115, 26125, 26140,
-26150, 26160, 26172, 26182, 26193, 26203, 26214, 26224, 26234, 26244, 26254, 26264, 26274, 26285, 26296, 26306,
-26316, 26326, 26336, 26347, 26357, 26367, 26377, 26387, 26397, 26407, 26417, 26429, 26439, 26449, 26460, 26470,
-26480, 26491, 26501, 26511, 26521, 26534, 26544, 26555, 26565, 26575, 26585, 26596, 26606, 26617, 26627, 26643,
-26653, 26663, 26673, 26683, 26693, 26704, 26715, 26727, 26737, 26747, 26757, 26767, 26778, 26789, 26799, 26809,
-26820, 26831, 26841, 26851, 26861, 26873, 26884, 26894, 26905, 26915, 26928, 26939, 26949, 26963, 26973, 26984,
-26994, 27004, 27018, 27028, 27040, 27051, 27063, 27073, 27083, 27094, 27106, 27117, 27129, 27139, 27151, 27161,
-27171, 27182, 27192, 27204, 27214, 27224, 27234, 27249, 27262, 27273, 27287, 27298, 27308, 27320, 27330, 27340,
-27350, 27364, 27376, 27386, 27396, 27407, 27419, 27431, 27442, 27453, 27463, 27474, 27485, 27495, 27507, 27517,
-27529, 27541, 27551, 27561, 27571, 27581, 27593, 27603, 27615, 27627, 27639, 27650, 27661, 27671, 27683, 27694,
-27704, 27714, 27725, 27735, 27746, 27757, 27768, 27778, 27788, 27798, 27809, 27819, 27832, 27842, 27852, 27862,
-27872, 27882, 27892, 27908, 27918, 27929, 27941, 27951, 27961, 27972, 27991, 28001, 28012, 28023, 28034, 28044,
-28054, 28074, 28084, 28095, 28106, 28117, 28127, 28137, 28147, 28160, 28170, 28181, 28191, 28201, 28214, 28227,
-28237, 28247, 28258, 28270, 28283, 28300, 28310, 28320, 28330, 28342, 28352, 28362, 28372, 28382, 28395, 28407,
-28417, 28428, 28438, 28448, 28458, 28470, 28481, 28495, 28505, 28516, 28526, 28536, 28546, 28556, 28566, 28576,
-28586, 28597, 28608, 28618, 28628, 28638, 28648, 28659, 28669, 28679, 28689, 28699, 28710, 28720, 28732, 28744,
-28756, 28766, 28779, 28789, 28801, 28814, 28824, 28836, 28846, 28856, 28872, 28883, 28893, 28913, 28925, 28935,
-28948, 28958, 28971, 28982, 28993, 29003, 29013, 29024, 29036, 29049, 29060, 29071, 29081, 29096, 29106, 29118,
-29128, 29138, 29148, 29158, 29173, 29183, 29193, 29203, 29213, 29224, 29234, 29244, 29254, 29264, 29274, 29287,
-29297, 29307, 29319, 29330, 29344, 29356, 29366, 29377, 29388, 29398, 29408, 29420, 29431, 29442, 29453, 29463,
-29474, 29484, 29494, 29507, 29517, 29527, 29539, 29550, 29560, 29571, 29582, 29592, 29602, 29613, 29623, 29634,
-29644, 29654, 29664, 29674, 29684, 29694, 29705, 29722, 29732, 29742, 29753, 29763, 29773, 29783, 29794, 29805,
-29822, 29833, 29848, 29858, 29870, 29881, 29896, 29907, 29918, 29928, 29938, 29948, 29958, 29969, 29980, 29990,
-30000, 30010, 30020, 30030, 30041, 30052, 30063, 30073, 30085, 30095, 30105, 30115, 30129, 30140, 30150, 30162,
-30172, 30183, 30193, 30204, 30215, 30226, 30236, 30246, 30256, 30266, 30276, 30290, 30300, 30311, 30321, 30331,
-30341, 30352, 30362, 30372, 30382, 30392, 30402, 30412, 30422, 30432, 30442, 30452, 30462, 30472, 30482, 30492,
-30502, 30516, 30526, 30538, 30550, 30560, 30570, 30580, 30590, 30603, 30613, 30623, 30634, 30645, 30655, 30665,
-30677, 30687, 30697, 30707, 30722, 30732, 30749, 30759, 30770, 30783, 30796, 30812, 30824, 30834, 30844, 30854,
-30865, 30877, 30887, 30897, 30907, 30917, 30928, 30938, 30948, 30959, 30970, 30982, 30992, 31002, 31013, 31025,
-31035, 31045, 31055, 31066, 31077, 31090, 31100, 31114, 31124, 31137, 31147, 31160, 31170, 31183, 31194, 31204,
-31216, 31227, 31239, 31249, 31259, 31271, 31281, 31291, 31301, 31311, 31321, 31331, 31341, 31352, 31362, 31376,
-31390, 31401, 31411, 31423, 31433, 31443, 31453, 31464, 31476, 31486, 31496, 31508, 31518, 31528, 31539, 31549,
-31559, 31569, 31581, 31591, 31601, 31620, 31630, 31640, 31653, 31663, 31674, 31684, 31695, 31705, 31716, 31730,
-31740, 31750, 31761, 31771, 31781, 31793, 31805, 31818, 31828, 31838, 31849, 31859, 31869, 31879, 31890, 31902,
-31912, 31922, 31932, 31943, 31954, 31964, 31974, 31986, 31998, 32008, 32018, 32028, 32038, 32048, 32058, 32068,
-32078, 32089, 32099, 32110, 32120, 32130, 32140, 32150, 32162, 32172, 32182, 32194, 32204, 32215, 32225, 32235,
-32245, 32256, 32266, 32277, 32287, 32299, 32309, 32319, 32330, 32340, 32350, 32361, 32371, 32381, 32391, 32401,
-32411, 32566, 32579, 32589, 32600, 32611, 32621, 32631, 32642, 32652, 32662, 32673, 32685, 32696, 32707, 32718,
-32731, 32741, 32751, 32761, 32771, 32781, 32791, 32801, 32812, 32822, 32832, 32842, 32854, 32864, 32877, 32887,
-32897, 32907, 32918, 32929, 32939, 32952, 32963, 32973, 32983, 32993, 33005, 33016, 33026, 33046, 33056, 33068,
-33081, 33093, 33104, 33119, 33129, 33140, 33151, 33162, 33173, 33184, 33198, 33208, 33218, 33229, 33239, 33249,
-33259, 33269, 33279, 33289, 33299, 33309, 33320, 33330, 33344, 33355, 33366, 33376, 33386, 33396, 33406, 33417,
-33428, 33439, 33449, 33459, 33469, 33488, 33498, 33508, 33519, 33529, 33539, 33550, 33560, 33570, 33580, 33590,
-33600, 33610, 33620, 33648, 33659, 33669, 33682, 33692, 33702, 33713, 33725, 33735, 33745, 33756, 33768, 33778,
-33788, 33798, 33809, 33824, 33834, 33845, 33861, 33871, 33881, 33891, 33901, 33911, 33921, 33931, 33941, 33951,
-33961, 33972, 33982, 33992, 34003, 34023, 34033, 34043, 34054, 34064, 34074, 34084, 34095, 34109, 34120, 34130,
-34140, 34152, 34167, 34177, 34187, 34199, 34210, 34220, 34230, 34241, 34251, 34261, 34271, 34281, 34291, 34302,
-34314, 34326, 34337, 34349, 34360, 34370, 34381, 34391, 34401, 34411, 34421, 34440, 34451, 34465, 34475, 34485,
-34495, 34505, 34516, 34526, 34537, 34552, 34562, 34573, 34584, 34595, 34606, 34617, 34627, 34637, 34647, 34657,
-34670, 34680, 34690, 34700, 34711, 34722, 34732, 34746, 34756, 34766, 34777, 34787, 34797, 34807, 34817, 34827,
-34837, 34847, 34861, 34873, 34883, 34893, 34903, 34913, 34923, 34933, 34943, 34955, 34966, 34976, 34986, 34996,
-35006, 35018, 35028, 35038, 35048, 35058, 35068, 35078, 35088, 35098, 35109, 35120, 35130, 35140, 35151, 35162,
-35172, 35182, 35194, 35206, 35216, 35226, 35237, 35247, 35258, 35282, 35292, 35302, 35313, 35325, 35335, 35345,
-35355, 35365, 35375, 35386, 35397, 35408, 35419, 35429, 35440, 35450, 35460, 35471, 35481, 35491, 35501, 35511,
-35522, 35532, 35542, 35552, 35563, 35573, 35583, 35594, 35604, 35614, 35624, 35635, 35646, 35656, 35666, 35676,
-35686, 35696, 35708, 35722, 35732, 35742, 35895, 35905, 35915, 35925, 35937, 35947, 35957, 35970, 35980, 35992,
-36002, 36012, 36022, 36032, 36042, 36053, 36064, 36074, 36085, 36095, 36105, 36115, 36196, 36206, 36223, 36234,
-36245, 36255, 36267, 36277, 36288, 36298, 36308, 36319, 36330, 36340, 36351, 36361, 36372, 36382, 36394, 36404,
-36416, 36426, 36436, 36446, 36457, 36468, 36481, 36491, 36501, 36513, 36523, 36533, 36544, 36554, 36564, 36575,
-36587, 36599, 36610, 36620, 36630, 36640, 36650, 36660, 36670, 36681, 36691, 36701, 36763, 36773, 36783, 36794,
-36804, 36814, 36826, 36836, 36846, 36856, 36866, 36876, 36886, 36896, 36906, 36916, 36926, 36937, 36947, 36957,
-36967, 36978, 36988, 36999, 37009, 37019, 37029, 37039, 37053, 37063, 37074, 37084, 37096, 37108, 37118, 37128,
-37138, 37148, 37159, 37169, 37180, 37191, 37202, 37217, 37228, 37239, 37249, 37259, 37269, 37281, 37291, 37301,
-37311, 37321, 37331, 37341, 37351, 37361, 37371, 37381, 37392, 37404, 37414, 37424, 37434, 37444, 37454, 37464,
-37474, 37486, 37496, 37507, 37517, 37527, 37540, 37551, 37561, 37571, 37581, 37591, 37601, 37612, 37624, 37634,
-37645, 37656, 37666, 37676, 37686, 37700, 37712, 37722, 37732, 37742, 37754, 37768, 37778, 37790, 37800, 37812,
-37825, 37835, 37846, 37857, 37879, 37889, 37901, 37911, 37921, 37931, 37941, 37951, 37962, 37973, 37983, 37994,
-38005, 38015, 38263, 38274, 38284, 38294, 38304, 38315, 38326, 38339, 38349, 38360, 38370, 38428, 38438, 38449,
-38459, 38475, 38486, 38497, 38508, 38518, 38529, 38539, 38549, 38559, 38569, 38579, 38592, 38602, 38613, 38623,
-38633, 38646, 38656, 38666, 38678, 38689, 38704, 38717, 38728, 38738, 38748, 38758, 38769, 38779, 38789, 38799,
-38809, 38819, 38829, 38840, 38851, 38861, 38871, 38881, 38893, 38903, 38913, 38924, 38934, 38944, 38955, 38965,
-38980, 38990, 39000, 39010, 39020, 39080, 39092, 39103, 39116, 39131, 39141, 39151, 39164, 39175, 39185, 39195,
-39206, 39217, 39227, 39237, 39248, 39259, 39318, 39333, 39344, 39354, 39364, 39376, 39386, 39399, 39409, 39419,
-39429, 39439, 39449, 39459, 39469, 39479, 39489, 39499, 39509, 39519, 39529, 39592, 39602, 39612, 39622, 39632,
-39643, 39653, 39663, 39673, 39683, 39693, 39704, 39714, 39725, 39735, 39745, 39755, 39765, 39777, 39787, 39797,
-39807, 39817, 39827, 39837, 39847, 39857, 39867, 39878, 39888, 39899, 39909, 39919, 39929, 39940, 39951, 39961,
-39971, 39981, 39991, 40001, 40014, 40024, 40035, 40046, 40056, 40165, 40176, 40194, 40206, 40216, 40227, 40239,
-40250, 40260, 40272, 40284, 40297, 40310, 40323, 40333, 40343, 40353, 40363, 40373, 40383, 40393, 40403, 40414,
-40425, 40435, 40445, 40455, 40465, 40475, 40565, 40575, 40587, 40597, 40607, 40617, 40627, 40638, 40648, 40658,
-40668, 40679, 40689, 40699, 40711, 40721, 40731, 40742, 40753, 40763, 40773, 40783, 40794, 40806, 40816, 40826,
-40845, 40855, 40865, 65281, 65291, 65301, 65311, 65321, 65331, 65341, 65351, 65361, 65371, 65381, 65391, 65401,
-65411, 65421, 65431, 65507
-            });
-
-        testBytes = theseBytes(new int[]{
-0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
-96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
-143, 162, 194, 161, 241, 161, 242, 143, 162, 240, /*92,*/ 143, 162, 195, 161, 248,
-161, 175, 143, 162, 237, 143, 162, 236, 162, 204, 143, 162, 238, 143, 162, 180,
-161, 235, 161, 222, 161, 173, 162, 249, 143, 162, 177, 143, 162, 235, 143, 162,
-196, 143, 170, 162, 143, 170, 161, 143, 170, 164, 143, 170, 170, 143, 170, 163,
-143, 170, 169, 143, 169, 161, 143, 170, 174, 143, 170, 178, 143, 170, 177, 143,
-170, 180, 143, 170, 179, 143, 170, 192, 143, 170, 191, 143, 170, 194, 143, 170,
-193, 143, 170, 208, 143, 170, 210, 143, 170, 209, 143, 170, 212, 143, 170, 216,
-143, 170, 211, 161, 223, 143, 169, 172, 143, 170, 227, 143, 170, 226, 143, 170,
-229, 143, 170, 228, 143, 170, 242, 143, 169, 176, 143, 169, 206, 143, 171, 162,
-143, 171, 161, 143, 171, 164, 143, 171, 170, 143, 171, 163, 143, 171, 169, 143,
-169, 193, 143, 171, 174, 143, 171, 178, 143, 171, 177, 143, 171, 180, 143, 171,
-179, 143, 171, 192, 143, 171, 191, 143, 171, 194, 143, 171, 193, 143, 169, 195,
-143, 171, 208, 143, 171, 210, 143, 171, 209, 143, 171, 212, 143, 171, 216, 143,
-171, 211, 161, 224, 143, 169, 204, 143, 171, 227, 143, 171, 226, 143, 171, 229,
-143, 171, 228, 143, 171, 242, 143, 169, 208, 143, 171, 243, 143, 170, 167, 143,
-170, 175, 143, 170, 182, 143, 170, 189, 143, 170, 197, 143, 170, 200, 143, 171,
-203, 143, 171, 206, 143, 169, 173, 143, 170, 221, 143, 169, 175, 143, 170, 232,
-143, 171, 245, 143, 170, 166, 143, 170, 237, 143, 171, 185, 143, 162, 176, 143,
-162, 175, 143, 162, 184, 143, 166, 233, 166, 168, 166, 178, 143, 166, 242, 166,
-199, 166, 209, 143, 166, 250, 167, 167, 143, 167, 203, 167, 166, 167, 177, 167,
-187, 167, 212, 167, 223, 167, 233, 167, 215, 143, 167, 251, 161, 190, 161, 200,
-161, 196, 162, 243, 162, 168, 161, 238, 143, 162, 241, 143, 162, 239, 162, 171,
-162, 205, 162, 207, 162, 187, 162, 229, 162, 202, 161, 232, 162, 226, 161, 226,
-162, 227, 162, 190, 162, 221, 162, 222, 168, 161, 168, 163, 168, 177, 168, 178,
-168, 184, 168, 181, 168, 182, 162, 163, 162, 165, 162, 167, 162, 161, 162, 254,
-161, 250, 161, 234, 162, 246, 161, 161, 161, 212, 161, 204, 164, 161, 164, 171,
-164, 181, 164, 191, 164, 201, 164, 211, 164, 221, 164, 231, 164, 241, 161, 171,
-165, 165, 165, 175, 165, 185, 165, 195, 165, 205, 165, 215, 165, 225, 165, 235,
-165, 245, 176, 236, 190, 229, 179, 238, 190, 231, 143, 176, 169, 182, 250, 208,
-167, 143, 176, 178, 143, 176, 179, 143, 176, 181, 143, 176, 183, 198, 253, 180,
-165, 205, 189, 184, 223, 176, 161, 203, 242, 208, 183, 191, 205, 208, 188, 208,
-186, 201, 213, 143, 176, 201, 208, 193, 208, 195, 180, 235, 143, 176, 214, 143,
-176, 217, 143, 176, 221, 191, 173, 143, 176, 231, 143, 176, 235, 143, 176, 238,
-143, 176, 223, 143, 176, 242, 202, 187, 187, 200, 143, 177, 162, 143, 177, 168,
-176, 205, 213, 165, 191, 175, 202, 216, 143, 177, 187, 208, 215, 208, 216, 189,
-164, 202, 240, 143, 177, 203, 143, 177, 207, 143, 177, 211, 143, 177, 216, 208,
-235, 182, 230, 143, 177, 223, 143, 177, 228, 208, 243, 143, 177, 236, 143, 177,
-242, 194, 166, 208, 250, 143, 177, 251, 143, 178, 163, 143, 178, 167, 143, 178,
-172, 208, 253, 183, 185, 209, 161, 143, 178, 185, 143, 178, 189, 193, 206, 143,
-178, 197, 202, 200, 143, 178, 202, 143, 178, 210, 209, 179, 143, 178, 218, 143,
-178, 223, 209, 184, 189, 188, 143, 178, 231, 197, 222, 143, 178, 237, 209, 194,
-197, 181, 209, 196, 209, 198, 209, 204, 180, 167, 209, 209, 186, 227, 143, 178,
-252, 143, 179, 161, 143, 179, 164, 244, 165, 189, 232, 209, 224, 189, 208, 209,
-227, 209, 230, 143, 179, 183, 143, 179, 184, 209, 233, 183, 244, 196, 230, 193,
-176, 143, 179, 193, 143, 179, 199, 143, 179, 201, 143, 179, 203, 143, 179, 206,
-143, 179, 209, 143, 179, 212, 178, 195, 197, 216, 207, 171, 179, 175, 143, 179,
-232, 240, 213, 143, 179, 239, 210, 171, 143, 179, 246, 188, 219, 202, 241, 210,
-183, 186, 252, 210, 186, 143, 180, 175, 210, 190, 143, 180, 182, 143, 180, 183,
-198, 238, 143, 180, 187, 143, 180, 190, 210, 203, 210, 204, 143, 180, 198, 206,
-210, 143, 180, 204, 210, 209, 143, 180, 212, 187, 178, 193, 208, 188, 232, 143,
-180, 224, 194, 254, 143, 180, 227, 210, 222, 177, 165, 143, 180, 230, 200, 221,
-143, 180, 236, 202, 173, 202, 242, 198, 221, 143, 180, 244, 188, 254, 204, 163,
-204, 191, 143, 181, 164, 210, 240, 143, 181, 170, 143, 181, 173, 143, 181, 179,
-143, 181, 183, 143, 181, 185, 211, 166, 211, 175, 143, 181, 191, 143, 181, 193,
-143, 181, 197, 143, 181, 202, 176, 162, 143, 181, 206, 143, 181, 209, 211, 177,
-143, 181, 217, 211, 183, 143, 181, 225, 211, 193, 143, 181, 232, 143, 181, 236,
-180, 238, 183, 246, 143, 181, 244, 143, 181, 245, 143, 181, 249, 143, 182, 161,
-143, 182, 165, 143, 182, 167, 143, 182, 168, 143, 182, 170, 143, 182, 175, 143,
-182, 179, 178, 222, 143, 182, 182, 143, 182, 188, 143, 182, 195, 143, 182, 199,
-143, 182, 200, 180, 239, 143, 182, 210, 211, 230, 211, 231, 211, 233, 143, 182,
-221, 143, 182, 225, 143, 182, 231, 143, 182, 233, 211, 244, 211, 247, 143, 182,
-244, 143, 182, 250, 143, 182, 252, 185, 241, 143, 183, 165, 143, 183, 168, 143,
-183, 171, 143, 183, 177, 143, 183, 182, 212, 173, 143, 183, 188, 212, 175, 212,
-179, 143, 183, 197, 143, 183, 205, 212, 180, 212, 181, 212, 182, 143, 183, 220,
-143, 183, 225, 212, 184, 143, 183, 230, 143, 183, 231, 212, 191, 199, 184, 143,
-183, 239, 143, 183, 243, 180, 240, 143, 183, 251, 194, 196, 143, 184, 165, 180,
-174, 190, 236, 143, 184, 172, 143, 184, 173, 197, 227, 186, 201, 143, 184, 183,
-212, 199, 143, 184, 185, 143, 184, 189, 202, 232, 143, 184, 199, 203, 207, 143,
-184, 206, 143, 184, 208, 195, 197, 212, 219, 212, 224, 143, 184, 221, 143, 184,
-222, 212, 232, 202, 209, 143, 184, 228, 143, 184, 231, 194, 231, 188, 186, 212,
-243, 198, 224, 143, 184, 244, 143, 184, 248, 212, 252, 143, 185, 162, 143, 185,
-167, 199, 165, 143, 185, 172, 143, 185, 174, 197, 202, 143, 185, 182, 143, 185,
-185, 187, 207, 213, 172, 143, 185, 195, 143, 185, 198, 176, 249, 213, 178, 143,
-185, 210, 143, 185, 211, 143, 185, 215, 213, 183, 213, 180, 143, 185, 223, 186,
-167, 143, 185, 228, 143, 185, 231, 143, 185, 235, 143, 185, 238, 143, 185, 243,
-143, 185, 246, 143, 185, 251, 213, 191, 183, 249, 213, 197, 143, 186, 167, 143,
-186, 169, 143, 186, 171, 143, 186, 174, 213, 201, 213, 202, 143, 186, 182, 196,
-220, 213, 206, 213, 210, 143, 186, 187, 213, 212, 204, 210, 213, 216, 213, 218,
-143, 186, 196, 177, 167, 143, 186, 205, 176, 184, 205, 168, 143, 186, 213, 205,
-198, 213, 227, 143, 186, 221, 143, 186, 224, 178, 201, 213, 237, 195, 254, 188,
-247, 176, 211, 213, 245, 143, 186, 235, 213, 248, 143, 186, 244, 198, 244, 213,
-252, 214, 161, 143, 186, 248, 193, 216, 214, 165, 214, 168, 143, 187, 169, 214,
-170, 143, 187, 174, 193, 187, 143, 187, 181, 214, 176, 214, 180, 143, 187, 187,
-143, 187, 188, 178, 229, 143, 187, 192, 214, 183, 191, 242, 214, 194, 214, 193,
-143, 187, 201, 143, 187, 203, 143, 187, 206, 143, 187, 211, 214, 201, 214, 191,
-191, 243, 214, 205, 143, 187, 226, 143, 187, 230, 143, 187, 232, 214, 211, 143,
-187, 240, 143, 230, 244, 214, 217, 143, 187, 247, 214, 221, 192, 238, 185, 170,
-184, 202, 180, 172, 200, 193, 214, 230, 214, 231, 191, 227, 194, 211, 203, 185,
-214, 243, 143, 188, 181, 143, 188, 184, 143, 188, 187, 180, 179, 205, 196, 200,
-223, 196, 236, 214, 249, 143, 188, 201, 176, 195, 143, 188, 207, 206, 247, 179,
-199, 215, 163, 215, 168, 215, 172, 215, 176, 143, 188, 223, 181, 221, 143, 188,
-227, 184, 204, 188, 229, 143, 188, 239, 143, 188, 244, 143, 188, 247, 143, 188,
-250, 201, 167, 190, 180, 143, 189, 166, 183, 194, 143, 189, 171, 215, 208, 143,
-189, 178, 200, 249, 143, 189, 183, 191, 180, 199, 166, 187, 214, 143, 189, 195,
-178, 247, 199, 176, 215, 221, 143, 189, 210, 143, 189, 213, 143, 189, 217, 215,
-226, 143, 189, 220, 143, 189, 222, 215, 240, 143, 189, 228, 215, 239, 178, 184,
-183, 195, 143, 189, 236, 188, 189, 143, 189, 243, 143, 189, 246, 216, 166, 143,
-189, 253, 143, 190, 161, 190, 240, 143, 190, 170, 143, 190, 173, 193, 218, 194,
-198, 216, 185, 216, 180, 143, 190, 188, 182, 242, 216, 195, 143, 190, 202, 216,
-198, 143, 190, 209, 216, 216, 216, 215, 183, 197, 216, 213, 143, 190, 216, 216,
-220, 216, 225, 143, 190, 229, 198, 180, 183, 251, 143, 190, 239, 216, 234, 178,
-251, 143, 190, 246, 216, 239, 196, 168, 216, 246, 143, 191, 167, 178, 230, 216,
-254, 192, 239, 217, 165, 204, 225, 143, 191, 182, 143, 191, 184, 143, 191, 189,
-143, 191, 191, 202, 177, 200, 227, 217, 183, 143, 191, 197, 185, 179, 143, 191,
-201, 202, 250, 217, 187, 195, 180, 217, 188, 192, 219, 143, 191, 214, 143, 191,
-216, 189, 166, 217, 205, 143, 191, 225, 182, 180, 143, 191, 228, 143, 191, 231,
-193, 222, 194, 170, 143, 191, 244, 143, 191, 248, 143, 191, 252, 199, 177, 143,
-192, 167, 199, 211, 143, 192, 174, 191, 228, 183, 199, 143, 192, 180, 143, 192,
-183, 217, 231, 143, 192, 189, 217, 226, 143, 192, 195, 217, 236, 143, 192, 201,
-217, 211, 217, 238, 143, 192, 213, 183, 200, 143, 192, 217, 197, 166, 143, 192,
-230, 143, 192, 231, 204, 206, 183, 226, 143, 192, 238, 143, 192, 242, 143, 192,
-247, 199, 197, 179, 201, 143, 193, 161, 143, 193, 166, 218, 166, 197, 167, 181,
-188, 218, 177, 218, 181, 143, 193, 185, 143, 193, 188, 143, 193, 192, 143, 193,
-196, 218, 189, 202, 252, 218, 195, 143, 193, 206, 218, 201, 143, 193, 210, 218,
-202, 143, 193, 213, 202, 184, 200, 195, 218, 207, 192, 205, 187, 219, 202, 253,
-218, 211, 143, 193, 232, 143, 193, 236, 180, 251, 189, 220, 143, 193, 242, 218,
-224, 143, 193, 249, 218, 230, 143, 194, 166, 143, 194, 172, 195, 235, 143, 194,
-179, 143, 194, 182, 143, 194, 187, 179, 162, 218, 242, 195, 210, 218, 247, 218,
-245, 218, 248, 196, 170, 143, 194, 217, 219, 162, 143, 194, 224, 143, 194, 227,
-219, 163, 219, 165, 143, 194, 234, 219, 170, 194, 216, 205, 173, 143, 194, 241,
-196, 171, 219, 176, 188, 235, 181, 224, 143, 194, 249, 194, 188, 197, 206, 143,
-195, 161, 219, 191, 143, 195, 166, 219, 199, 143, 195, 170, 143, 195, 175, 219,
-197, 143, 195, 177, 143, 195, 181, 143, 195, 188, 199, 240, 143, 195, 193, 219,
-207, 219, 211, 143, 195, 184, 198, 202, 192, 242, 143, 195, 204, 143, 195, 207,
-143, 195, 212, 143, 195, 214, 143, 195, 217, 182, 205, 143, 195, 223, 201, 176,
-143, 195, 228, 143, 195, 233, 199, 223, 219, 231, 143, 195, 241, 143, 195, 245,
-196, 244, 219, 238, 180, 254, 143, 195, 254, 143, 196, 165, 220, 168, 143, 196,
-173, 220, 170, 220, 166, 196, 199, 191, 250, 220, 176, 220, 191, 143, 196, 193,
-143, 196, 195, 201, 246, 220, 194, 143, 196, 204, 143, 196, 209, 207, 176, 186,
-231, 207, 177, 220, 213, 143, 196, 222, 143, 196, 225, 220, 201, 185, 189, 143,
-196, 232, 143, 196, 234, 220, 229, 220, 223, 143, 196, 244, 143, 196, 245, 201,
-184, 220, 235, 220, 211, 220, 247, 220, 237, 143, 197, 170, 181, 204, 220, 243,
-143, 197, 180, 143, 197, 182, 143, 197, 187, 221, 161, 220, 253, 221, 168, 221,
-166, 221, 165, 143, 197, 206, 143, 197, 210, 143, 197, 213, 143, 197, 216, 221,
-178, 205, 243, 143, 197, 226, 143, 197, 230, 178, 164, 205, 223, 182, 214, 221,
-188, 143, 197, 244, 143, 197, 247, 143, 197, 249, 186, 208, 143, 197, 254, 189,
-222, 221, 205, 143, 198, 166, 143, 198, 171, 221, 213, 143, 198, 178, 143, 198,
-182, 221, 218, 221, 219, 221, 221, 143, 198, 192, 143, 198, 195, 143, 198, 199,
-181, 164, 221, 230, 143, 198, 209, 177, 202, 181, 225, 143, 198, 218, 180, 192,
-221, 233, 143, 198, 226, 143, 198, 230, 221, 235, 198, 217, 178, 173, 203, 215,
-203, 247, 202, 168, 143, 198, 246, 200, 231, 143, 198, 254, 143, 199, 163, 222,
-165, 143, 199, 170, 143, 199, 171, 143, 199, 174, 222, 172, 196, 197, 143, 199,
-184, 143, 199, 186, 190, 244, 143, 199, 189, 143, 199, 192, 179, 189, 179, 164,
-143, 199, 198, 205, 176, 143, 199, 203, 143, 199, 206, 143, 199, 208, 143, 199,
-212, 143, 199, 215, 222, 204, 143, 199, 221, 143, 199, 225, 189, 223, 143, 199,
-231, 222, 189, 222, 188, 222, 219, 178, 185, 143, 199, 237, 222, 220, 222, 218,
-143, 199, 251, 143, 200, 161, 222, 208, 143, 200, 165, 200, 174, 189, 224, 143,
-200, 170, 222, 228, 205, 207, 143, 200, 178, 143, 200, 183, 222, 237, 194, 218,
-143, 200, 187, 223, 163, 181, 249, 143, 200, 196, 143, 200, 198, 199, 249, 143,
-200, 204, 143, 200, 208, 222, 243, 143, 200, 212, 143, 200, 217, 189, 225, 196,
-172, 223, 166, 223, 173, 143, 200, 231, 143, 200, 237, 143, 200, 240, 223, 186,
-143, 200, 248, 183, 227, 143, 200, 254, 223, 190, 143, 201, 162, 143, 201, 163,
-223, 171, 143, 201, 169, 143, 201, 173, 223, 198, 223, 202, 195, 245, 223, 208,
-143, 201, 182, 143, 201, 185, 143, 201, 189, 143, 201, 192, 178, 208, 143, 201,
-198, 143, 201, 201, 177, 234, 143, 201, 208, 143, 201, 210, 223, 220, 223, 218,
-206, 245, 143, 201, 218, 223, 223, 223, 216, 223, 226, 143, 201, 230, 177, 235,
-143, 201, 234, 143, 201, 236, 193, 179, 143, 201, 242, 143, 201, 247, 223, 230,
-143, 201, 254, 223, 236, 143, 202, 162, 223, 239, 223, 237, 244, 166, 223, 241,
-143, 202, 174, 223, 245, 197, 245, 223, 246, 143, 202, 187, 187, 184, 223, 253,
-224, 162, 143, 202, 193, 143, 202, 194, 143, 202, 197, 224, 166, 224, 170, 224,
-172, 224, 175, 143, 202, 211, 143, 202, 215, 203, 210, 143, 202, 224, 143, 202,
-227, 224, 182, 224, 183, 181, 190, 184, 164, 190, 245, 143, 202, 242, 143, 202,
-245, 143, 202, 247, 224, 195, 198, 200, 224, 198, 143, 203, 162, 143, 203, 167,
-224, 200, 143, 203, 173, 143, 203, 177, 205, 177, 143, 203, 184, 143, 203, 185,
-224, 213, 189, 195, 143, 203, 199, 224, 217, 143, 203, 207, 143, 203, 210, 143,
-203, 215, 143, 203, 220, 143, 203, 225, 143, 203, 227, 178, 209, 143, 203, 236,
-143, 203, 240, 188, 238, 183, 190, 143, 203, 248, 184, 189, 206, 176, 143, 204,
-168, 143, 204, 170, 143, 204, 178, 143, 204, 182, 143, 204, 184, 143, 204, 189,
-143, 204, 192, 143, 204, 194, 143, 204, 199, 224, 247, 143, 204, 208, 143, 204,
-213, 224, 229, 143, 204, 226, 143, 204, 231, 143, 204, 234, 143, 204, 238, 143,
-204, 242, 143, 204, 245, 225, 166, 143, 204, 252, 143, 204, 254, 185, 249, 197,
-188, 225, 180, 197, 196, 196, 174, 225, 183, 143, 205, 180, 206, 177, 225, 191,
-143, 205, 187, 143, 205, 189, 143, 205, 196, 193, 193, 143, 205, 201, 225, 207,
-225, 215, 225, 214, 143, 205, 211, 225, 218, 143, 205, 216, 143, 205, 221, 143,
-205, 225, 225, 224, 143, 205, 231, 143, 205, 236, 143, 205, 242, 143, 205, 247,
-225, 240, 143, 206, 161, 143, 206, 167, 204, 254, 225, 245, 225, 252, 143, 206,
-179, 197, 208, 143, 206, 182, 187, 169, 226, 173, 143, 206, 193, 200, 233, 226,
-176, 226, 179, 143, 206, 205, 226, 181, 143, 206, 209, 226, 187, 196, 190, 189,
-226, 226, 190, 143, 206, 222, 143, 206, 228, 226, 197, 143, 206, 234, 143, 206,
-239, 143, 206, 243, 143, 206, 248, 143, 206, 253, 143, 207, 163, 143, 207, 168,
-226, 208, 226, 211, 143, 207, 176, 143, 207, 179, 143, 207, 182, 143, 207, 186,
-226, 218, 143, 207, 189, 143, 207, 192, 143, 207, 195, 182, 235, 192, 208, 186,
-189, 226, 230, 143, 207, 212, 181, 206, 203, 164, 185, 220, 143, 207, 225, 143,
-207, 228, 143, 207, 234, 200, 163, 226, 239, 226, 238, 200, 234, 143, 207, 244,
-202, 203, 143, 207, 252, 143, 208, 161, 226, 252, 200, 216, 227, 162, 143, 208,
-173, 176, 235, 143, 208, 185, 143, 208, 188, 143, 208, 190, 143, 208, 191, 143,
-208, 196, 143, 208, 200, 143, 208, 203, 143, 208, 207, 143, 208, 211, 227, 175,
-190, 205, 143, 208, 220, 143, 208, 223, 227, 180, 143, 208, 229, 143, 208, 235,
-143, 208, 238, 143, 208, 242, 143, 208, 244, 143, 208, 249, 143, 208, 252, 199,
-233, 190, 206, 176, 220, 143, 209, 172, 143, 209, 176, 143, 209, 178, 143, 209,
-181, 227, 202, 227, 203, 143, 209, 192, 178, 186, 143, 209, 198, 190, 247, 143,
-209, 206, 143, 209, 208, 143, 209, 211, 143, 209, 216, 143, 209, 219, 227, 221,
-143, 209, 223, 227, 227, 143, 209, 229, 227, 234, 227, 237, 143, 209, 234, 143,
-209, 239, 143, 209, 242, 181, 232, 143, 209, 244, 227, 250, 227, 252, 227, 247,
-143, 210, 163, 143, 210, 167, 195, 222, 228, 184, 228, 170, 228, 172, 143, 210,
-180, 143, 210, 182, 228, 176, 143, 210, 189, 143, 210, 191, 143, 210, 196, 200,
-207, 228, 189, 143, 210, 207, 198, 198, 143, 210, 212, 143, 210, 218, 143, 210,
-224, 228, 194, 143, 210, 231, 143, 210, 233, 143, 210, 237, 228, 213, 143, 210,
-244, 228, 216, 143, 210, 254, 143, 211, 164, 202, 198, 143, 211, 171, 143, 211,
-173, 206, 179, 143, 211, 176, 228, 234, 228, 236, 143, 211, 184, 143, 211, 187,
-228, 245, 228, 246, 143, 211, 199, 228, 250, 181, 234, 143, 211, 205, 143, 211,
-209, 229, 162, 143, 211, 215, 186, 217, 186, 176, 193, 200, 229, 174, 143, 211,
-230, 229, 179, 229, 177, 143, 211, 238, 143, 211, 243, 143, 211, 249, 143, 211,
-252, 229, 194, 188, 250, 143, 212, 166, 143, 212, 169, 143, 212, 174, 143, 212,
-177, 229, 206, 143, 212, 184, 143, 212, 187, 143, 212, 179, 229, 208, 143, 212,
-194, 229, 213, 203, 165, 229, 220, 143, 212, 206, 193, 161, 191, 165, 229, 229,
-229, 234, 143, 212, 221, 229, 239, 143, 212, 226, 143, 212, 229, 229, 251, 180,
-204, 143, 212, 240, 230, 163, 230, 169, 143, 212, 250, 143, 212, 254, 200, 237,
-230, 176, 230, 181, 143, 213, 171, 143, 213, 174, 143, 213, 178, 230, 192, 143,
-213, 183, 143, 213, 185, 143, 213, 187, 143, 213, 190, 143, 213, 194, 230, 203,
-185, 205, 143, 213, 203, 204, 215, 230, 212, 143, 213, 216, 204, 237, 143, 213,
-226, 230, 216, 192, 187, 143, 213, 228, 143, 213, 231, 191, 166, 143, 213, 234,
-207, 190, 190, 211, 184, 212, 143, 213, 241, 143, 213, 242, 176, 223, 143, 213,
-245, 143, 213, 250, 184, 213, 143, 213, 253, 182, 187, 187, 233, 143, 214, 170,
-143, 214, 175, 143, 214, 178, 196, 177, 143, 214, 183, 201, 229, 231, 181, 143,
-214, 193, 231, 171, 194, 220, 231, 174, 231, 178, 231, 177, 143, 214, 209, 231,
-187, 231, 190, 231, 193, 143, 214, 220, 143, 214, 224, 143, 214, 226, 143, 214,
-231, 143, 214, 236, 218, 170, 143, 214, 240, 143, 214, 244, 143, 214, 247, 143,
-214, 248, 231, 217, 143, 215, 161, 143, 215, 165, 143, 215, 167, 231, 226, 143,
-215, 171, 231, 232, 143, 215, 180, 143, 215, 184, 231, 236, 143, 215, 195, 203,
-167, 178, 234, 143, 215, 207, 143, 215, 209, 143, 215, 212, 143, 215, 216, 231,
-249, 231, 247, 183, 212, 232, 173, 143, 215, 233, 143, 215, 234, 195, 227, 232,
-166, 183, 213, 143, 215, 227, 143, 215, 253, 178, 174, 232, 174, 143, 216, 168,
-143, 216, 174, 143, 216, 176, 205, 233, 232, 207, 143, 216, 183, 143, 216, 187,
-186, 218, 143, 216, 191, 232, 203, 143, 216, 196, 143, 216, 198, 143, 216, 201,
-232, 206, 232, 212, 232, 226, 143, 216, 207, 143, 216, 212, 143, 216, 217, 198,
-161, 232, 211, 232, 216, 143, 216, 232, 190, 213, 143, 216, 236, 232, 231, 143,
-216, 240, 143, 216, 244, 143, 216, 247, 143, 216, 251, 143, 216, 254, 143, 217,
-162, 143, 217, 166, 143, 217, 171, 232, 209, 143, 217, 178, 177, 182, 143, 217,
-183, 143, 217, 188, 202, 195, 232, 254, 143, 217, 197, 143, 217, 201, 207, 207,
-233, 177, 143, 217, 216, 143, 217, 220, 177, 242, 143, 217, 228, 204, 244, 143,
-217, 232, 207, 206, 143, 217, 242, 233, 185, 143, 217, 247, 200, 205, 143, 217,
-252, 233, 193, 233, 190, 221, 177, 143, 218, 174, 205, 246, 143, 218, 178, 143,
-218, 183, 233, 200, 143, 218, 188, 143, 218, 193, 195, 238, 143, 218, 200, 143,
-218, 237, 233, 206, 143, 218, 210, 233, 219, 143, 218, 218, 143, 218, 222, 233,
-217, 233, 220, 233, 221, 233, 222, 194, 253, 203, 170, 233, 235, 195, 216, 143,
-218, 254, 143, 219, 162, 143, 219, 166, 143, 219, 172, 143, 219, 174, 233, 251,
-143, 219, 177, 233, 253, 233, 247, 234, 167, 143, 219, 192, 143, 219, 196, 234,
-165, 143, 219, 203, 205, 230, 234, 175, 143, 219, 214, 143, 219, 217, 143, 219,
-222, 143, 219, 226, 234, 187, 143, 219, 232, 143, 219, 237, 234, 192, 143, 219,
-248, 143, 219, 250, 234, 197, 143, 220, 164, 222, 167, 179, 185, 185, 213, 234,
-206, 234, 210, 182, 222, 194, 222, 194, 181, 143, 220, 190, 143, 220, 192, 184,
-211, 143, 220, 195, 143, 220, 197, 234, 227, 143, 220, 206, 234, 235, 234, 236,
-234, 233, 143, 220, 214, 179, 236, 143, 220, 222, 234, 243, 143, 220, 228, 143,
-220, 233, 234, 247, 143, 220, 240, 143, 220, 243, 235, 162, 143, 220, 250, 143,
-220, 254, 202, 164, 143, 221, 166, 179, 208, 143, 221, 173, 235, 178, 235, 180,
-179, 209, 235, 185, 191, 168, 143, 221, 189, 143, 221, 193, 143, 221, 197, 143,
-221, 199, 235, 194, 235, 196, 143, 221, 210, 191, 199, 143, 221, 217, 186, 190,
-235, 199, 143, 221, 229, 181, 205, 143, 221, 235, 235, 209, 143, 221, 243, 143,
-221, 248, 235, 216, 198, 201, 143, 222, 162, 235, 219, 180, 210, 207, 192, 235,
-227, 235, 221, 143, 222, 180, 143, 222, 183, 143, 222, 191, 235, 226, 143, 222,
-189, 235, 245, 235, 240, 235, 244, 143, 222, 201, 143, 222, 202, 201, 232, 183,
-217, 181, 196, 143, 222, 213, 218, 206, 143, 222, 221, 143, 222, 224, 195, 171,
-236, 175, 143, 222, 233, 236, 181, 190, 221, 208, 174, 143, 222, 250, 236, 186,
-203, 198, 236, 194, 185, 215, 192, 213, 236, 202, 178, 236, 194, 177, 143, 223,
-178, 199, 229, 188, 193, 143, 223, 187, 143, 223, 191, 143, 223, 194, 236, 219,
-192, 214, 143, 223, 201, 143, 223, 202, 177, 219, 143, 223, 209, 143, 223, 211,
-143, 223, 214, 143, 223, 218, 143, 223, 222, 143, 223, 227, 143, 223, 230, 236,
-240, 236, 238, 143, 223, 242, 236, 245, 236, 244, 143, 223, 250, 236, 247, 237,
-169, 236, 253, 143, 224, 171, 236, 254, 143, 224, 177, 143, 224, 181, 143, 224,
-184, 189, 179, 237, 175, 237, 179, 143, 224, 198, 237, 186, 191, 200, 143, 224,
-209, 143, 224, 212, 188, 214, 143, 224, 219, 198, 240, 237, 199, 143, 224, 225,
-143, 224, 230, 237, 210, 143, 224, 235, 143, 224, 239, 206, 216, 143, 224, 248,
-237, 217, 237, 219, 143, 225, 166, 143, 225, 170, 191, 201, 143, 225, 177, 237,
-231, 202, 213, 203, 248, 183, 222, 237, 233, 143, 225, 195, 143, 225, 197, 237,
-254, 143, 225, 203, 143, 225, 206, 237, 248, 194, 164, 143, 225, 212, 143, 225,
-216, 238, 167, 238, 166, 198, 187, 143, 225, 223, 143, 225, 226, 238, 175, 206,
-203, 237, 238, 205, 184, 143, 225, 241, 143, 225, 245, 238, 184, 143, 225, 251,
-143, 226, 163, 143, 226, 173, 143, 226, 169, 201, 244, 143, 226, 178, 143, 226,
-179, 143, 226, 185, 238, 192, 143, 226, 193, 143, 226, 199, 143, 226, 203, 143,
-226, 209, 143, 226, 212, 188, 242, 143, 226, 220, 189, 183, 185, 243, 143, 226,
-228, 238, 204, 143, 226, 237, 143, 226, 240, 238, 208, 238, 211, 143, 226, 254,
-238, 216, 143, 227, 164, 191, 203, 182, 252, 143, 227, 179, 143, 227, 182, 143,
-227, 187, 143, 227, 193, 143, 227, 198, 143, 227, 203, 143, 227, 207, 143, 227,
-213, 197, 180, 143, 227, 223, 143, 227, 226, 200, 173, 143, 227, 236, 143, 227,
-242, 189, 198, 143, 227, 251, 143, 227, 254, 143, 228, 164, 143, 228, 169, 238,
-248, 143, 228, 181, 143, 228, 188, 143, 228, 193, 143, 228, 200, 143, 228, 205,
-181, 248, 143, 228, 212, 143, 228, 214, 191, 238, 239, 162, 207, 163, 143, 228,
-230, 238, 253, 143, 228, 235, 143, 228, 241, 143, 228, 243, 239, 171, 143, 229,
-161, 143, 229, 167, 143, 229, 172, 143, 229, 176, 143, 229, 181, 143, 229, 183,
-143, 229, 188, 143, 229, 195, 239, 178, 182, 192, 143, 229, 207, 143, 229, 212,
-143, 229, 217, 143, 229, 222, 239, 197, 239, 195, 239, 196, 143, 229, 231, 143,
-229, 236, 143, 229, 238, 143, 229, 241, 239, 206, 239, 209, 239, 216, 196, 185,
-239, 217, 143, 230, 164, 239, 221, 239, 224, 143, 230, 173, 143, 230, 176, 239,
-234, 239, 235, 198, 174, 239, 243, 201, 236, 143, 230, 201, 143, 230, 203, 193,
-203, 239, 251, 143, 230, 214, 143, 230, 217, 240, 165, 198, 171, 143, 230, 224,
-231, 161, 240, 168, 143, 230, 233, 143, 230, 237, 143, 230, 240, 191, 253, 143,
-230, 242, 240, 186, 143, 230, 249, 143, 230, 250, 206, 237, 188, 251, 206, 238,
-240, 195, 143, 231, 167, 240, 199, 240, 201, 240, 205, 192, 196, 240, 208, 240,
-211, 240, 215, 143, 231, 191, 240, 217, 240, 223, 143, 231, 199, 240, 228, 202,
-220, 143, 231, 210, 240, 231, 143, 231, 223, 143, 231, 228, 143, 231, 235, 240,
-236, 143, 231, 240, 202, 199, 240, 243, 143, 231, 249, 143, 231, 252, 143, 232,
-161, 143, 232, 167, 143, 232, 170, 179, 220, 180, 234, 143, 232, 180, 143, 232,
-185, 201, 247, 143, 232, 190, 143, 232, 195, 143, 232, 199, 200, 244, 143, 232,
-202, 200, 211, 187, 244, 143, 232, 209, 143, 232, 211, 143, 232, 216, 143, 232,
-220, 143, 232, 223, 143, 232, 230, 241, 189, 241, 190, 143, 232, 242, 188, 243,
-241, 198, 143, 232, 251, 143, 233, 162, 194, 204, 195, 243, 143, 233, 170, 143,
-233, 173, 241, 209, 241, 211, 241, 215, 241, 214, 241, 217, 143, 233, 194, 143,
-233, 197, 241, 219, 143, 233, 204, 143, 233, 207, 241, 225, 241, 229, 241, 233,
-185, 252, 143, 233, 218, 241, 238, 143, 233, 228, 143, 233, 231, 143, 233, 236,
-143, 233, 240, 241, 249, 143, 233, 247, 143, 233, 254, 143, 234, 167, 242, 163,
-242, 166, 143, 234, 178, 143, 234, 182, 179, 161, 143, 234, 187, 143, 234, 189,
-143, 234, 194, 143, 234, 200, 143, 234, 205, 143, 234, 209, 143, 234, 215, 242,
-184, 143, 234, 223, 143, 234, 226, 143, 234, 230, 143, 234, 234, 242, 196, 143,
-234, 242, 194, 228, 143, 234, 247, 143, 234, 251, 143, 235, 161, 242, 218, 143,
-235, 168, 143, 235, 172, 143, 235, 177, 201, 201, 143, 235, 186, 143, 235, 188,
-143, 235, 194, 143, 235, 200, 143, 235, 205, 143, 235, 211, 242, 233, 196, 187,
-242, 236, 143, 235, 222, 178, 170, 143, 235, 225, 242, 245, 143, 235, 229, 143,
-235, 234, 242, 247, 243, 165, 177, 173, 143, 235, 248, 143, 235, 252, 143, 236,
-163, 143, 236, 167, 143, 236, 173, 143, 236, 175, 243, 170, 143, 236, 180, 143,
-236, 183, 143, 236, 186, 243, 186, 143, 236, 193, 143, 236, 198, 143, 236, 202,
-243, 191, 143, 236, 207, 143, 236, 210, 243, 193, 243, 195, 188, 175, 243, 200,
-243, 203, 206, 219, 243, 207, 143, 236, 238, 221, 224, 143, 236, 242, 185, 245,
-243, 217, 143, 236, 247, 143, 236, 252, 243, 228, 243, 231, 143, 237, 168, 143,
-237, 175, 143, 237, 178, 143, 237, 182, 201, 161, 143, 237, 194, 240, 237, 143,
-237, 202, 243, 245, 143, 237, 210, 143, 237, 214, 206, 182, 143, 237, 222, 143,
-237, 224, 161, 170, 161, 220, 163, 181, 161, 169, 163, 201, 163, 211, 161, 207,
-163, 231, 163, 241, 161, 208, 142, 165, 142, 175, 142, 185, 142, 195, 142, 205,
-142, 215, 161, 177
-            });
-
-        super.setUp();
+  @Override public void test_CodecDynamic() throws CharacterCodingException {
+    encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+    decoder.onMalformedInput(CodingErrorAction.REPORT);
+    CharBuffer inputCB = CharBuffer.allocate(65536);
+    for (char codePoint = 0; codePoint <= 0xfffe; ++codePoint) {
+      if (encoder.canEncode(codePoint)) {
+        inputCB.put(codePoint);
+      }
     }
-
-    @Override
-    public void test_CodecDynamic () throws CharacterCodingException {
-        encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
-        decoder.onMalformedInput(CodingErrorAction.REPORT);
-        CharBuffer inputCB = CharBuffer.allocate(65536);
-        for (int code = 32; code <= 65533; code ++) {
-            if ((encoder.canEncode((char) code))
-                    && (code != 165) && (code != 8254)) {
-                inputCB.put((char) code);
-            }
-        }
-        inputCB.rewind();
-        ByteBuffer intermediateBB = encoder.encode(inputCB);
-        inputCB.rewind();
-        intermediateBB.rewind();
-        CharBuffer outputCB = decoder.decode(intermediateBB);
-        outputCB.rewind();
-        assertEqualCBs("decode(encode(A)) must be identical with A!",
-                inputCB, outputCB);
-    }
-
+    inputCB.rewind();
+    ByteBuffer intermediateBB = encoder.encode(inputCB);
+    inputCB.rewind();
+    intermediateBB.rewind();
+    CharBuffer outputCB = decoder.decode(intermediateBB);
+    outputCB.rewind();
+    assertEqualCBs("decode(encode(A)) must be identical with A!", inputCB, outputCB);
+  }
 }
diff --git a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP_Android.java b/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP_Android.java
deleted file mode 100644
index 373c97f..0000000
--- a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP_Android.java
+++ /dev/null
@@ -1,523 +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 libcore.java.nio.charset;
-
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.CodingErrorAction;
-
-/** Note: ICU behaves differently from the RI */
-
-public class OldCharset_MultiByte_EUC_JP_Android extends OldCharset_AbstractTest {
-
-    protected void setUp() throws Exception {
-        charsetName = "EUC-JP";
-
-        testChars = theseChars(new int[]{
-0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
-96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
-161, 162, 163, 164, /*165,*/ 166, 167, 168, 169, 170, 172, 174, 175, 176, 177, 180,
-182, 184, 186, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
-204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
-221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
-237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
-253, 254, 255, 256, 266, 278, 288, 298, 308, 318, 328, 338, 348, 358, 368, 378,
-461, 471, 501, 711, 728, 900, 910, 920, 931, 941, 951, 961, 971, 1025, 1035, 1045,
-1055, 1065, 1075, 1085, 1095, 1105, 1115, 8208, 8220, 8230, 8240, 8251, 8451, 8470, 8482, 8592,
-8658, 8704, 8715, 8730, 8743, 8756, 8786, 8800, 8810, 8834, 8869, 8978, 9472, 9484, 9495, 9507,
-9519, 9531, 9547, 9632, 9650, 9660, 9670, 9711, 9733, 9792, 9834, 12288, 12298, 12308, 12353, 12363,
-12373, 12383, 12393, 12403, 12413, 12423, 12433, 12443, 12453, 12463, 12473, 12483, 12493, 12503, 12513, 12523,
-12533, 19968, 19978, 19988, 19998, 20008, 20018, 20028, 20039, 20049, 20060, 20072, 20083, 20094, 20104, 20114,
-20124, 20134, 20144, 20154, 20164, 20174, 20184, 20194, 20205, 20215, 20225, 20235, 20245, 20270, 20280, 20290,
-20300, 20310, 20320, 20330, 20341, 20351, 20361, 20371, 20381, 20395, 20405, 20415, 20425, 20436, 20447, 20462,
-20472, 20484, 20494, 20504, 20514, 20524, 20534, 20544, 20554, 20565, 20575, 20586, 20596, 20608, 20618, 20628,
-20638, 20650, 20660, 20670, 20681, 20691, 20701, 20711, 20721, 20731, 20742, 20752, 20762, 20775, 20785, 20795,
-20805, 20815, 20826, 20836, 20846, 20856, 20866, 20876, 20886, 20896, 20906, 20916, 20926, 20936, 20946, 20956,
-20966, 20976, 20986, 20996, 21006, 21016, 21026, 21038, 21048, 21059, 21069, 21079, 21089, 21102, 21112, 21122,
-21132, 21142, 21152, 21162, 21172, 21182, 21192, 21202, 21212, 21222, 21232, 21242, 21253, 21263, 21273, 21283,
-21293, 21304, 21314, 21324, 21335, 21345, 21356, 21367, 21378, 21390, 21400, 21412, 21422, 21432, 21442, 21452,
-21462, 21472, 21482, 21493, 21505, 21515, 21530, 21542, 21553, 21563, 21574, 21585, 21598, 21608, 21619, 21629,
-21640, 21650, 21660, 21670, 21681, 21691, 21702, 21720, 21730, 21740, 21750, 21760, 21772, 21782, 21802, 21813,
-21824, 21834, 21846, 21856, 21883, 21894, 21905, 21916, 21927, 21938, 21951, 21961, 21971, 21982, 21993, 22006,
-22021, 22031, 22041, 22057, 22067, 22077, 22089, 22100, 22110, 22120, 22130, 22144, 22154, 22164, 22174, 22184,
-22195, 22206, 22216, 22227, 22237, 22247, 22257, 22269, 22279, 22289, 22299, 22309, 22319, 22331, 22341, 22351,
-22369, 22379, 22389, 22399, 22409, 22419, 22429, 22439, 22451, 22461, 22471, 22482, 22492, 22502, 22512, 22522,
-22532, 22549, 22559, 22570, 22580, 22591, 22601, 22612, 22622, 22632, 22642, 22652, 22663, 22675, 22685, 22696,
-22706, 22716, 22727, 22737, 22748, 22761, 22771, 22781, 22793, 22803, 22813, 22823, 22833, 22846, 22856, 22866,
-22877, 22887, 22898, 22908, 22922, 22933, 22943, 22956, 22967, 22977, 22987, 23001, 23011, 23022, 23035, 23049,
-23059, 23070, 23080, 23093, 23104, 23116, 23130, 23141, 23159, 23179, 23190, 23200, 23212, 23224, 23234, 23244,
-23254, 23264, 23274, 23285, 23296, 23307, 23318, 23329, 23340, 23350, 23360, 23371, 23381, 23391, 23401, 23411,
-23421, 23431, 23441, 23451, 23461, 23471, 23481, 23491, 23501, 23511, 23521, 23531, 23541, 23551, 23561, 23571,
-23582, 23592, 23602, 23612, 23622, 23632, 23642, 23652, 23662, 23673, 23687, 23697, 23709, 23720, 23730, 23740,
-23751, 23762, 23773, 23784, 23794, 23805, 23815, 23825, 23835, 23846, 23857, 23869, 23880, 23890, 23900, 23913,
-23923, 23934, 23944, 23954, 23965, 23975, 23986, 23996, 24007, 24018, 24029, 24039, 24049, 24059, 24070, 24081,
-24091, 24101, 24111, 24125, 24135, 24145, 24155, 24168, 24178, 24188, 24199, 24213, 24224, 24234, 24245, 24255,
-24265, 24275, 24285, 24296, 24307, 24318, 24328, 24339, 24349, 24359, 24369, 24379, 24389, 24400, 24411, 24422,
-24432, 24442, 24452, 24463, 24473, 24484, 24494, 24504, 24515, 24525, 24535, 24545, 24555, 24565, 24575, 24586,
-24596, 24607, 24617, 24627, 24640, 24650, 24660, 24671, 24681, 24693, 24703, 24713, 24723, 24733, 24743, 24753,
-24763, 24773, 24783, 24793, 24803, 24816, 24826, 24838, 24848, 24858, 24871, 24881, 24892, 24902, 24915, 24925,
-24935, 24945, 24955, 24967, 24977, 24988, 24999, 25010, 25020, 25030, 25040, 25052, 25062, 25074, 25084, 25095,
-25105, 25115, 25126, 25136, 25147, 25158, 25168, 25178, 25188, 25198, 25209, 25219, 25229, 25239, 25254, 25265,
-25275, 25285, 25295, 25305, 25322, 25332, 25342, 25352, 25363, 25375, 25385, 25397, 25407, 25417, 25427, 25445,
-25457, 25467, 25479, 25490, 25502, 25512, 25522, 25533, 25544, 25554, 25564, 25577, 25587, 25606, 25616, 25628,
-25638, 25648, 25658, 25675, 25688, 25699, 25709, 25720, 25731, 25743, 25753, 25763, 25773, 25785, 25796, 25806,
-25816, 25826, 25836, 25846, 25856, 25866, 25876, 25886, 25897, 25908, 25918, 25928, 25938, 25949, 25959, 25970,
-25981, 25991, 26001, 26011, 26021, 26031, 26041, 26051, 26062, 26072, 26082, 26092, 26105, 26115, 26125, 26140,
-26150, 26160, 26172, 26182, 26193, 26203, 26214, 26224, 26234, 26244, 26254, 26264, 26274, 26285, 26296, 26306,
-26316, 26326, 26336, 26347, 26357, 26367, 26377, 26387, 26397, 26407, 26417, 26429, 26439, 26449, 26460, 26470,
-26480, 26491, 26501, 26511, 26521, 26534, 26544, 26555, 26565, 26575, 26585, 26596, 26606, 26617, 26627, 26643,
-26653, 26663, 26673, 26683, 26693, 26704, 26715, 26727, 26737, 26747, 26757, 26767, 26778, 26789, 26799, 26809,
-26820, 26831, 26841, 26851, 26861, 26873, 26884, 26894, 26905, 26915, 26928, 26939, 26949, 26963, 26973, 26984,
-26994, 27004, 27018, 27028, 27040, 27051, 27063, 27073, 27083, 27094, 27106, 27117, 27129, 27139, 27151, 27161,
-27171, 27182, 27192, 27204, 27214, 27224, 27234, 27249, 27262, 27273, 27287, 27298, 27308, 27320, 27330, 27340,
-27350, 27364, 27376, 27386, 27396, 27407, 27419, 27431, 27442, 27453, 27463, 27474, 27485, 27495, 27507, 27517,
-27529, 27541, 27551, 27561, 27571, 27581, 27593, 27603, 27615, 27627, 27639, 27650, 27661, 27671, 27683, 27694,
-27704, 27714, 27725, 27735, 27746, 27757, 27768, 27778, 27788, 27798, 27809, 27819, 27832, 27842, 27852, 27862,
-27872, 27882, 27892, 27908, 27918, 27929, 27941, 27951, 27961, 27972, 27991, 28001, 28012, 28023, 28034, 28044,
-28054, 28074, 28084, 28095, 28106, 28117, 28127, 28137, 28147, 28160, 28170, 28181, 28191, 28201, 28214, 28227,
-28237, 28247, 28258, 28270, 28283, 28300, 28310, 28320, 28330, 28342, 28352, 28362, 28372, 28382, 28395, 28407,
-28417, 28428, 28438, 28448, 28458, 28470, 28481, 28495, 28505, 28516, 28526, 28536, 28546, 28556, 28566, 28576,
-28586, 28597, 28608, 28618, 28628, 28638, 28648, 28659, 28669, 28679, 28689, 28699, 28710, 28720, 28732, 28744,
-28756, 28766, 28779, 28789, 28801, 28814, 28824, 28836, 28846, 28856, 28872, 28883, 28893, 28913, 28925, 28935,
-28948, 28958, 28971, 28982, 28993, 29003, 29013, 29024, 29036, 29049, 29060, 29071, 29081, 29096, 29106, 29118,
-29128, 29138, 29148, 29158, 29173, 29183, 29193, 29203, 29213, 29224, 29234, 29244, 29254, 29264, 29274, 29287,
-29297, 29307, 29319, 29330, 29344, 29356, 29366, 29377, 29388, 29398, 29408, 29420, 29431, 29442, 29453, 29463,
-29474, 29484, 29494, 29507, 29517, 29527, 29539, 29550, 29560, 29571, 29582, 29592, 29602, 29613, 29623, 29634,
-29644, 29654, 29664, 29674, 29684, 29694, 29705, 29722, 29732, 29742, 29753, 29763, 29773, 29783, 29794, 29805,
-29822, 29833, 29848, 29858, 29870, 29881, 29896, 29907, 29918, 29928, 29938, 29948, 29958, 29969, 29980, 29990,
-30000, 30010, 30020, 30030, 30041, 30052, 30063, 30073, 30085, 30095, 30105, 30115, 30129, 30140, 30150, 30162,
-30172, 30183, 30193, 30204, 30215, 30226, 30236, 30246, 30256, 30266, 30276, 30290, 30300, 30311, 30321, 30331,
-30341, 30352, 30362, 30372, 30382, 30392, 30402, 30412, 30422, 30432, 30442, 30452, 30462, 30472, 30482, 30492,
-30502, 30516, 30526, 30538, 30550, 30560, 30570, 30580, 30590, 30603, 30613, 30623, 30634, 30645, 30655, 30665,
-30677, 30687, 30697, 30707, 30722, 30732, 30749, 30759, 30770, 30783, 30796, 30812, 30824, 30834, 30844, 30854,
-30865, 30877, 30887, 30897, 30907, 30917, 30928, 30938, 30948, 30959, 30970, 30982, 30992, 31002, 31013, 31025,
-31035, 31045, 31055, 31066, 31077, 31090, 31100, 31114, 31124, 31137, 31147, 31160, 31170, 31183, 31194, 31204,
-31216, 31227, 31239, 31249, 31259, 31271, 31281, 31291, 31301, 31311, 31321, 31331, 31341, 31352, 31362, 31376,
-31390, 31401, 31411, 31423, 31433, 31443, 31453, 31464, 31476, 31486, 31496, 31508, 31518, 31528, 31539, 31549,
-31559, 31569, 31581, 31591, 31601, 31620, 31630, 31640, 31653, 31663, 31674, 31684, 31695, 31705, 31716, 31730,
-31740, 31750, 31761, 31771, 31781, 31793, 31805, 31818, 31828, 31838, 31849, 31859, 31869, 31879, 31890, 31902,
-31912, 31922, 31932, 31943, 31954, 31964, 31974, 31986, 31998, 32008, 32018, 32028, 32038, 32048, 32058, 32068,
-32078, 32089, 32099, 32110, 32120, 32130, 32140, 32150, 32162, 32172, 32182, 32194, 32204, 32215, 32225, 32235,
-32245, 32256, 32266, 32277, 32287, 32299, 32309, 32319, 32330, 32340, 32350, 32361, 32371, 32381, 32391, 32401,
-32411, 32566, 32579, 32589, 32600, 32611, 32621, 32631, 32642, 32652, 32662, 32673, 32685, 32696, 32707, 32718,
-32731, 32741, 32751, 32761, 32771, 32781, 32791, 32801, 32812, 32822, 32832, 32842, 32854, 32864, 32877, 32887,
-32897, 32907, 32918, 32929, 32939, 32952, 32963, 32973, 32983, 32993, 33005, 33016, 33026, 33046, 33056, 33068,
-33081, 33093, 33104, 33119, 33129, 33140, 33151, 33162, 33173, 33184, 33198, 33208, 33218, 33229, 33239, 33249,
-33259, 33269, 33279, 33289, 33299, 33309, 33320, 33330, 33344, 33355, 33366, 33376, 33386, 33396, 33406, 33417,
-33428, 33439, 33449, 33459, 33469, 33488, 33498, 33508, 33519, 33529, 33539, 33550, 33560, 33570, 33580, 33590,
-33600, 33610, 33620, 33648, 33659, 33669, 33682, 33692, 33702, 33713, 33725, 33735, 33745, 33756, 33768, 33778,
-33788, 33798, 33809, 33824, 33834, 33845, 33861, 33871, 33881, 33891, 33901, 33911, 33921, 33931, 33941, 33951,
-33961, 33972, 33982, 33992, 34003, 34023, 34033, 34043, 34054, 34064, 34074, 34084, 34095, 34109, 34120, 34130,
-34140, 34152, 34167, 34177, 34187, 34199, 34210, 34220, 34230, 34241, 34251, 34261, 34271, 34281, 34291, 34302,
-34314, 34326, 34337, 34349, 34360, 34370, 34381, 34391, 34401, 34411, 34421, 34440, 34451, 34465, 34475, 34485,
-34495, 34505, 34516, 34526, 34537, 34552, 34562, 34573, 34584, 34595, 34606, 34617, 34627, 34637, 34647, 34657,
-34670, 34680, 34690, 34700, 34711, 34722, 34732, 34746, 34756, 34766, 34777, 34787, 34797, 34807, 34817, 34827,
-34837, 34847, 34861, 34873, 34883, 34893, 34903, 34913, 34923, 34933, 34943, 34955, 34966, 34976, 34986, 34996,
-35006, 35018, 35028, 35038, 35048, 35058, 35068, 35078, 35088, 35098, 35109, 35120, 35130, 35140, 35151, 35162,
-35172, 35182, 35194, 35206, 35216, 35226, 35237, 35247, 35258, 35282, 35292, 35302, 35313, 35325, 35335, 35345,
-35355, 35365, 35375, 35386, 35397, 35408, 35419, 35429, 35440, 35450, 35460, 35471, 35481, 35491, 35501, 35511,
-35522, 35532, 35542, 35552, 35563, 35573, 35583, 35594, 35604, 35614, 35624, 35635, 35646, 35656, 35666, 35676,
-35686, 35696, 35708, 35722, 35732, 35742, 35895, 35905, 35915, 35925, 35937, 35947, 35957, 35970, 35980, 35992,
-36002, 36012, 36022, 36032, 36042, 36053, 36064, 36074, 36085, 36095, 36105, 36115, 36196, 36206, 36223, 36234,
-36245, 36255, 36267, 36277, 36288, 36298, 36308, 36319, 36330, 36340, 36351, 36361, 36372, 36382, 36394, 36404,
-36416, 36426, 36436, 36446, 36457, 36468, 36481, 36491, 36501, 36513, 36523, 36533, 36544, 36554, 36564, 36575,
-36587, 36599, 36610, 36620, 36630, 36640, 36650, 36660, 36670, 36681, 36691, 36701, 36763, 36773, 36783, 36794,
-36804, 36814, 36826, 36836, 36846, 36856, 36866, 36876, 36886, 36896, 36906, 36916, 36926, 36937, 36947, 36957,
-36967, 36978, 36988, 36999, 37009, 37019, 37029, 37039, 37053, 37063, 37074, 37084, 37096, 37108, 37118, 37128,
-37138, 37148, 37159, 37169, 37180, 37191, 37202, 37217, 37228, 37239, 37249, 37259, 37269, 37281, 37291, 37301,
-37311, 37321, 37331, 37341, 37351, 37361, 37371, 37381, 37392, 37404, 37414, 37424, 37434, 37444, 37454, 37464,
-37474, 37486, 37496, 37507, 37517, 37527, 37540, 37551, 37561, 37571, 37581, 37591, 37601, 37612, 37624, 37634,
-37645, 37656, 37666, 37676, 37686, 37700, 37712, 37722, 37732, 37742, 37754, 37768, 37778, 37790, 37800, 37812,
-37825, 37835, 37846, 37857, 37879, 37889, 37901, 37911, 37921, 37931, 37941, 37951, 37962, 37973, 37983, 37994,
-38005, 38015, 38263, 38274, 38284, 38294, 38304, 38315, 38326, 38339, 38349, 38360, 38370, 38428, 38438, 38449,
-38459, 38475, 38486, 38497, 38508, 38518, 38529, 38539, 38549, 38559, 38569, 38579, 38592, 38602, 38613, 38623,
-38633, 38646, 38656, 38666, 38678, 38689, 38704, 38717, 38728, 38738, 38748, 38758, 38769, 38779, 38789, 38799,
-38809, 38819, 38829, 38840, 38851, 38861, 38871, 38881, 38893, 38903, 38913, 38924, 38934, 38944, 38955, 38965,
-38980, 38990, 39000, 39010, 39020, 39080, 39092, 39103, 39116, 39131, 39141, 39151, 39164, 39175, 39185, 39195,
-39206, 39217, 39227, 39237, 39248, 39259, 39318, 39333, 39344, 39354, 39364, 39376, 39386, 39399, 39409, 39419,
-39429, 39439, 39449, 39459, 39469, 39479, 39489, 39499, 39509, 39519, 39529, 39592, 39602, 39612, 39622, 39632,
-39643, 39653, 39663, 39673, 39683, 39693, 39704, 39714, 39725, 39735, 39745, 39755, 39765, 39777, 39787, 39797,
-39807, 39817, 39827, 39837, 39847, 39857, 39867, 39878, 39888, 39899, 39909, 39919, 39929, 39940, 39951, 39961,
-39971, 39981, 39991, 40001, 40014, 40024, 40035, 40046, 40056, 40165, 40176, 40194, 40206, 40216, 40227, 40239,
-40250, 40260, 40272, 40284, 40297, 40310, 40323, 40333, 40343, 40353, 40363, 40373, 40383, 40393, 40403, 40414,
-40425, 40435, 40445, 40455, 40465, 40475, 40565, 40575, 40587, 40597, 40607, 40617, 40627, 40638, 40648, 40658,
-40668, 40679, 40689, 40699, 40711, 40721, 40731, 40742, 40753, 40763, 40773, 40783, 40794, 40806, 40816, 40826,
-40845, 40855, 40865, 65281, 65291, 65301, 65311, 65321, 65331, 65341, 65351, 65361, 65371, 65381, 65391, 65401,
-65411, 65421, 65431, 65507
-            });
-
-        testBytes = theseBytes(new int[]{
-0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
-96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
-143, 162, 194, 142, 224, 142, 225, 143, 162, 240, 143, 162, 195, 161, 248, 161,
-175, 143, 162, 237, 143, 162, 236, 142, 226, 143, 162, 238, 143, 162, 180, 161,
-235, 161, 222, 161, 173, 162, 249, 143, 162, 177, 143, 162, 235, 143, 162, 196,
-143, 170, 162, 143, 170, 161, 143, 170, 164, 143, 170, 170, 143, 170, 163, 143,
-170, 169, 143, 169, 161, 143, 170, 174, 143, 170, 178, 143, 170, 177, 143, 170,
-180, 143, 170, 179, 143, 170, 192, 143, 170, 191, 143, 170, 194, 143, 170, 193,
-143, 170, 208, 143, 170, 210, 143, 170, 209, 143, 170, 212, 143, 170, 216, 143,
-170, 211, 161, 223, 143, 169, 172, 143, 170, 227, 143, 170, 226, 143, 170, 229,
-143, 170, 228, 143, 170, 242, 143, 169, 176, 143, 169, 206, 143, 171, 162, 143,
-171, 161, 143, 171, 164, 143, 171, 170, 143, 171, 163, 143, 171, 169, 143, 169,
-193, 143, 171, 174, 143, 171, 178, 143, 171, 177, 143, 171, 180, 143, 171, 179,
-143, 171, 192, 143, 171, 191, 143, 171, 194, 143, 171, 193, 143, 169, 195, 143,
-171, 208, 143, 171, 210, 143, 171, 209, 143, 171, 212, 143, 171, 216, 143, 171,
-211, 161, 224, 143, 169, 204, 143, 171, 227, 143, 171, 226, 143, 171, 229, 143,
-171, 228, 143, 171, 242, 143, 169, 208, 143, 171, 243, 143, 170, 167, 143, 170,
-175, 143, 170, 182, 143, 170, 189, 143, 170, 197, 143, 170, 200, 143, 171, 203,
-143, 171, 206, 143, 169, 173, 143, 170, 221, 143, 169, 175, 143, 170, 232, 143,
-171, 245, 143, 170, 166, 143, 170, 237, 143, 171, 185, 143, 162, 176, 143, 162,
-175, 143, 162, 184, 143, 166, 233, 166, 168, 166, 178, 143, 166, 242, 166, 199,
-166, 209, 143, 166, 250, 167, 167, 143, 167, 203, 167, 166, 167, 177, 167, 187,
-167, 212, 167, 223, 167, 233, 167, 215, 143, 167, 251, 161, 190, 161, 200, 161,
-196, 162, 243, 162, 168, 161, 238, 143, 162, 241, 143, 162, 239, 162, 171, 162,
-205, 162, 207, 162, 187, 162, 229, 162, 202, 161, 232, 162, 226, 161, 226, 162,
-227, 162, 190, 162, 221, 162, 222, 168, 161, 168, 163, 168, 177, 168, 178, 168,
-184, 168, 181, 168, 182, 162, 163, 162, 165, 162, 167, 162, 161, 162, 254, 161,
-250, 161, 234, 162, 246, 161, 161, 161, 212, 161, 204, 164, 161, 164, 171, 164,
-181, 164, 191, 164, 201, 164, 211, 164, 221, 164, 231, 164, 241, 161, 171, 165,
-165, 165, 175, 165, 185, 165, 195, 165, 205, 165, 215, 165, 225, 165, 235, 165,
-245, 176, 236, 190, 229, 179, 238, 190, 231, 143, 176, 169, 182, 250, 208, 167,
-143, 176, 178, 143, 176, 179, 143, 176, 181, 143, 176, 183, 198, 253, 180, 165,
-205, 189, 184, 223, 176, 161, 203, 242, 208, 183, 191, 205, 208, 188, 208, 186,
-201, 213, 143, 176, 201, 208, 193, 208, 195, 180, 235, 143, 176, 214, 143, 176,
-217, 143, 176, 221, 191, 173, 143, 176, 231, 143, 176, 235, 143, 176, 238, 143,
-176, 223, 143, 176, 242, 202, 187, 187, 200, 143, 177, 162, 143, 177, 168, 176,
-205, 213, 165, 191, 175, 202, 216, 143, 177, 187, 208, 215, 208, 216, 189, 164,
-202, 240, 143, 177, 203, 143, 177, 207, 143, 177, 211, 143, 177, 216, 208, 235,
-182, 230, 143, 177, 223, 143, 177, 228, 208, 243, 143, 177, 236, 143, 177, 242,
-194, 166, 208, 250, 143, 177, 251, 143, 178, 163, 143, 178, 167, 143, 178, 172,
-208, 253, 183, 185, 209, 161, 143, 178, 185, 143, 178, 189, 193, 206, 143, 178,
-197, 202, 200, 143, 178, 202, 143, 178, 210, 209, 179, 143, 178, 218, 143, 178,
-223, 209, 184, 189, 188, 143, 178, 231, 197, 222, 143, 178, 237, 209, 194, 197,
-181, 209, 196, 209, 198, 209, 204, 180, 167, 209, 209, 186, 227, 143, 178, 252,
-143, 179, 161, 143, 179, 164, 244, 165, 189, 232, 209, 224, 189, 208, 209, 227,
-209, 230, 143, 179, 183, 143, 179, 184, 209, 233, 183, 244, 196, 230, 193, 176,
-143, 179, 193, 143, 179, 199, 143, 179, 201, 143, 179, 203, 143, 179, 206, 143,
-179, 209, 143, 179, 212, 178, 195, 197, 216, 207, 171, 179, 175, 143, 179, 232,
-240, 213, 143, 179, 239, 210, 171, 143, 179, 246, 188, 219, 202, 241, 210, 183,
-186, 252, 210, 186, 143, 180, 175, 210, 190, 143, 180, 182, 143, 180, 183, 198,
-238, 143, 180, 187, 143, 180, 190, 210, 203, 210, 204, 143, 180, 198, 206, 210,
-143, 180, 204, 210, 209, 143, 180, 212, 187, 178, 193, 208, 188, 232, 143, 180,
-224, 194, 254, 143, 180, 227, 210, 222, 177, 165, 143, 180, 230, 200, 221, 143,
-180, 236, 202, 173, 202, 242, 198, 221, 143, 180, 244, 188, 254, 204, 163, 204,
-191, 143, 181, 164, 210, 240, 143, 181, 170, 143, 181, 173, 143, 181, 179, 143,
-181, 183, 143, 181, 185, 211, 166, 211, 175, 143, 181, 191, 143, 181, 193, 143,
-181, 197, 143, 181, 202, 176, 162, 143, 181, 206, 143, 181, 209, 211, 177, 143,
-181, 217, 211, 183, 143, 181, 225, 211, 193, 143, 181, 232, 143, 181, 236, 180,
-238, 183, 246, 143, 181, 244, 143, 181, 245, 143, 181, 249, 143, 182, 161, 143,
-182, 165, 143, 182, 167, 143, 182, 168, 143, 182, 170, 143, 182, 175, 143, 182,
-179, 178, 222, 143, 182, 182, 143, 182, 188, 143, 182, 195, 143, 182, 199, 143,
-182, 200, 180, 239, 143, 182, 210, 211, 230, 211, 231, 211, 233, 143, 182, 221,
-143, 182, 225, 143, 182, 231, 143, 182, 233, 211, 244, 211, 247, 143, 182, 244,
-143, 182, 250, 143, 182, 252, 185, 241, 143, 183, 165, 143, 183, 168, 143, 183,
-171, 143, 183, 177, 143, 183, 182, 212, 173, 143, 183, 188, 212, 175, 212, 179,
-143, 183, 197, 143, 183, 205, 212, 180, 212, 181, 212, 182, 143, 183, 220, 143,
-183, 225, 212, 184, 143, 183, 230, 143, 183, 231, 212, 191, 199, 184, 143, 183,
-239, 143, 183, 243, 180, 240, 143, 183, 251, 194, 196, 143, 184, 165, 180, 174,
-190, 236, 143, 184, 172, 143, 184, 173, 197, 227, 186, 201, 143, 184, 183, 212,
-199, 143, 184, 185, 143, 184, 189, 202, 232, 143, 184, 199, 203, 207, 143, 184,
-206, 143, 184, 208, 195, 197, 212, 219, 212, 224, 143, 184, 221, 143, 184, 222,
-212, 232, 202, 209, 143, 184, 228, 143, 184, 231, 194, 231, 188, 186, 212, 243,
-198, 224, 143, 184, 244, 143, 184, 248, 212, 252, 143, 185, 162, 143, 185, 167,
-199, 165, 143, 185, 172, 143, 185, 174, 197, 202, 143, 185, 182, 143, 185, 185,
-187, 207, 213, 172, 143, 185, 195, 143, 185, 198, 176, 249, 213, 178, 143, 185,
-210, 143, 185, 211, 143, 185, 215, 213, 183, 213, 180, 143, 185, 223, 186, 167,
-143, 185, 228, 143, 185, 231, 143, 185, 235, 143, 185, 238, 143, 185, 243, 143,
-185, 246, 143, 185, 251, 213, 191, 183, 249, 213, 197, 143, 186, 167, 143, 186,
-169, 143, 186, 171, 143, 186, 174, 213, 201, 213, 202, 143, 186, 182, 196, 220,
-213, 206, 213, 210, 143, 186, 187, 213, 212, 204, 210, 213, 216, 213, 218, 143,
-186, 196, 177, 167, 143, 186, 205, 176, 184, 205, 168, 143, 186, 213, 205, 198,
-213, 227, 143, 186, 221, 143, 186, 224, 178, 201, 213, 237, 195, 254, 188, 247,
-176, 211, 213, 245, 143, 186, 235, 213, 248, 143, 186, 244, 198, 244, 213, 252,
-214, 161, 143, 186, 248, 193, 216, 214, 165, 214, 168, 143, 187, 169, 214, 170,
-143, 187, 174, 193, 187, 143, 187, 181, 214, 176, 214, 180, 143, 187, 187, 143,
-187, 188, 178, 229, 143, 187, 192, 214, 183, 191, 242, 214, 194, 214, 193, 143,
-187, 201, 143, 187, 203, 143, 187, 206, 143, 187, 211, 214, 201, 214, 191, 191,
-243, 214, 205, 143, 187, 226, 143, 187, 230, 143, 187, 232, 214, 211, 143, 187,
-240, 143, 230, 244, 214, 217, 143, 187, 247, 214, 221, 192, 238, 185, 170, 184,
-202, 180, 172, 200, 193, 214, 230, 214, 231, 191, 227, 194, 211, 203, 185, 214,
-243, 143, 188, 181, 143, 188, 184, 143, 188, 187, 180, 179, 205, 196, 200, 223,
-196, 236, 214, 249, 143, 188, 201, 176, 195, 143, 188, 207, 206, 247, 179, 199,
-215, 163, 215, 168, 215, 172, 215, 176, 143, 188, 223, 181, 221, 143, 188, 227,
-184, 204, 188, 229, 143, 188, 239, 143, 188, 244, 143, 188, 247, 143, 188, 250,
-201, 167, 190, 180, 143, 189, 166, 183, 194, 143, 189, 171, 215, 208, 143, 189,
-178, 200, 249, 143, 189, 183, 191, 180, 199, 166, 187, 214, 143, 189, 195, 178,
-247, 199, 176, 215, 221, 143, 189, 210, 143, 189, 213, 143, 189, 217, 215, 226,
-143, 189, 220, 143, 189, 222, 215, 240, 143, 189, 228, 215, 239, 178, 184, 183,
-195, 143, 189, 236, 188, 189, 143, 189, 243, 143, 189, 246, 216, 166, 143, 189,
-253, 143, 190, 161, 190, 240, 143, 190, 170, 143, 190, 173, 193, 218, 194, 198,
-216, 185, 216, 180, 143, 190, 188, 182, 242, 216, 195, 143, 190, 202, 216, 198,
-143, 190, 209, 216, 216, 216, 215, 183, 197, 216, 213, 143, 190, 216, 216, 220,
-216, 225, 143, 190, 229, 198, 180, 183, 251, 143, 190, 239, 216, 234, 178, 251,
-143, 190, 246, 216, 239, 196, 168, 216, 246, 143, 191, 167, 178, 230, 216, 254,
-192, 239, 217, 165, 204, 225, 143, 191, 182, 143, 191, 184, 143, 191, 189, 143,
-191, 191, 202, 177, 200, 227, 217, 183, 143, 191, 197, 185, 179, 143, 191, 201,
-202, 250, 217, 187, 195, 180, 217, 188, 192, 219, 143, 191, 214, 143, 191, 216,
-189, 166, 217, 205, 143, 191, 225, 182, 180, 143, 191, 228, 143, 191, 231, 193,
-222, 194, 170, 143, 191, 244, 143, 191, 248, 143, 191, 252, 199, 177, 143, 192,
-167, 199, 211, 143, 192, 174, 191, 228, 183, 199, 143, 192, 180, 143, 192, 183,
-217, 231, 143, 192, 189, 217, 226, 143, 192, 195, 217, 236, 143, 192, 201, 217,
-211, 217, 238, 143, 192, 213, 183, 200, 143, 192, 217, 197, 166, 143, 192, 230,
-143, 192, 231, 204, 206, 183, 226, 143, 192, 238, 143, 192, 242, 143, 192, 247,
-199, 197, 179, 201, 143, 193, 161, 143, 193, 166, 218, 166, 197, 167, 181, 188,
-218, 177, 218, 181, 143, 193, 185, 143, 193, 188, 143, 193, 192, 143, 193, 196,
-218, 189, 202, 252, 218, 195, 143, 193, 206, 218, 201, 143, 193, 210, 218, 202,
-143, 193, 213, 202, 184, 200, 195, 218, 207, 192, 205, 187, 219, 202, 253, 218,
-211, 143, 193, 232, 143, 193, 236, 180, 251, 189, 220, 143, 193, 242, 218, 224,
-143, 193, 249, 218, 230, 143, 194, 166, 143, 194, 172, 195, 235, 143, 194, 179,
-143, 194, 182, 143, 194, 187, 179, 162, 218, 242, 195, 210, 218, 247, 218, 245,
-218, 248, 196, 170, 143, 194, 217, 219, 162, 143, 194, 224, 143, 194, 227, 219,
-163, 219, 165, 143, 194, 234, 219, 170, 194, 216, 205, 173, 143, 194, 241, 196,
-171, 219, 176, 188, 235, 181, 224, 143, 194, 249, 194, 188, 197, 206, 143, 195,
-161, 219, 191, 143, 195, 166, 219, 199, 143, 195, 170, 143, 195, 175, 219, 197,
-143, 195, 177, 143, 195, 181, 143, 195, 188, 199, 240, 143, 195, 193, 219, 207,
-219, 211, 143, 195, 184, 198, 202, 192, 242, 143, 195, 204, 143, 195, 207, 143,
-195, 212, 143, 195, 214, 143, 195, 217, 182, 205, 143, 195, 223, 201, 176, 143,
-195, 228, 143, 195, 233, 199, 223, 219, 231, 143, 195, 241, 143, 195, 245, 196,
-244, 219, 238, 180, 254, 143, 195, 254, 143, 196, 165, 220, 168, 143, 196, 173,
-220, 170, 220, 166, 196, 199, 191, 250, 220, 176, 220, 191, 143, 196, 193, 143,
-196, 195, 201, 246, 220, 194, 143, 196, 204, 143, 196, 209, 207, 176, 186, 231,
-207, 177, 220, 213, 143, 196, 222, 143, 196, 225, 220, 201, 185, 189, 143, 196,
-232, 143, 196, 234, 220, 229, 220, 223, 143, 196, 244, 143, 196, 245, 201, 184,
-220, 235, 220, 211, 220, 247, 220, 237, 143, 197, 170, 181, 204, 220, 243, 143,
-197, 180, 143, 197, 182, 143, 197, 187, 221, 161, 220, 253, 221, 168, 221, 166,
-221, 165, 143, 197, 206, 143, 197, 210, 143, 197, 213, 143, 197, 216, 221, 178,
-205, 243, 143, 197, 226, 143, 197, 230, 178, 164, 205, 223, 182, 214, 221, 188,
-143, 197, 244, 143, 197, 247, 143, 197, 249, 186, 208, 143, 197, 254, 189, 222,
-221, 205, 143, 198, 166, 143, 198, 171, 221, 213, 143, 198, 178, 143, 198, 182,
-221, 218, 221, 219, 221, 221, 143, 198, 192, 143, 198, 195, 143, 198, 199, 181,
-164, 221, 230, 143, 198, 209, 177, 202, 181, 225, 143, 198, 218, 180, 192, 221,
-233, 143, 198, 226, 143, 198, 230, 221, 235, 198, 217, 178, 173, 203, 215, 203,
-247, 202, 168, 143, 198, 246, 200, 231, 143, 198, 254, 143, 199, 163, 222, 165,
-143, 199, 170, 143, 199, 171, 143, 199, 174, 222, 172, 196, 197, 143, 199, 184,
-143, 199, 186, 190, 244, 143, 199, 189, 143, 199, 192, 179, 189, 179, 164, 143,
-199, 198, 205, 176, 143, 199, 203, 143, 199, 206, 143, 199, 208, 143, 199, 212,
-143, 199, 215, 222, 204, 143, 199, 221, 143, 199, 225, 189, 223, 143, 199, 231,
-222, 189, 222, 188, 222, 219, 178, 185, 143, 199, 237, 222, 220, 222, 218, 143,
-199, 251, 143, 200, 161, 222, 208, 143, 200, 165, 200, 174, 189, 224, 143, 200,
-170, 222, 228, 205, 207, 143, 200, 178, 143, 200, 183, 222, 237, 194, 218, 143,
-200, 187, 223, 163, 181, 249, 143, 200, 196, 143, 200, 198, 199, 249, 143, 200,
-204, 143, 200, 208, 222, 243, 143, 200, 212, 143, 200, 217, 189, 225, 196, 172,
-223, 166, 223, 173, 143, 200, 231, 143, 200, 237, 143, 200, 240, 223, 186, 143,
-200, 248, 183, 227, 143, 200, 254, 223, 190, 143, 201, 162, 143, 201, 163, 223,
-171, 143, 201, 169, 143, 201, 173, 223, 198, 223, 202, 195, 245, 223, 208, 143,
-201, 182, 143, 201, 185, 143, 201, 189, 143, 201, 192, 178, 208, 143, 201, 198,
-143, 201, 201, 177, 234, 143, 201, 208, 143, 201, 210, 223, 220, 223, 218, 206,
-245, 143, 201, 218, 223, 223, 223, 216, 223, 226, 143, 201, 230, 177, 235, 143,
-201, 234, 143, 201, 236, 193, 179, 143, 201, 242, 143, 201, 247, 223, 230, 143,
-201, 254, 223, 236, 143, 202, 162, 223, 239, 223, 237, 244, 166, 223, 241, 143,
-202, 174, 223, 245, 197, 245, 223, 246, 143, 202, 187, 187, 184, 223, 253, 224,
-162, 143, 202, 193, 143, 202, 194, 143, 202, 197, 224, 166, 224, 170, 224, 172,
-224, 175, 143, 202, 211, 143, 202, 215, 203, 210, 143, 202, 224, 143, 202, 227,
-224, 182, 224, 183, 181, 190, 184, 164, 190, 245, 143, 202, 242, 143, 202, 245,
-143, 202, 247, 224, 195, 198, 200, 224, 198, 143, 203, 162, 143, 203, 167, 224,
-200, 143, 203, 173, 143, 203, 177, 205, 177, 143, 203, 184, 143, 203, 185, 224,
-213, 189, 195, 143, 203, 199, 224, 217, 143, 203, 207, 143, 203, 210, 143, 203,
-215, 143, 203, 220, 143, 203, 225, 143, 203, 227, 178, 209, 143, 203, 236, 143,
-203, 240, 188, 238, 183, 190, 143, 203, 248, 184, 189, 206, 176, 143, 204, 168,
-143, 204, 170, 143, 204, 178, 143, 204, 182, 143, 204, 184, 143, 204, 189, 143,
-204, 192, 143, 204, 194, 143, 204, 199, 224, 247, 143, 204, 208, 143, 204, 213,
-224, 229, 143, 204, 226, 143, 204, 231, 143, 204, 234, 143, 204, 238, 143, 204,
-242, 143, 204, 245, 225, 166, 143, 204, 252, 143, 204, 254, 185, 249, 197, 188,
-225, 180, 197, 196, 196, 174, 225, 183, 143, 205, 180, 206, 177, 225, 191, 143,
-205, 187, 143, 205, 189, 143, 205, 196, 193, 193, 143, 205, 201, 225, 207, 225,
-215, 225, 214, 143, 205, 211, 225, 218, 143, 205, 216, 143, 205, 221, 143, 205,
-225, 225, 224, 143, 205, 231, 143, 205, 236, 143, 205, 242, 143, 205, 247, 225,
-240, 143, 206, 161, 143, 206, 167, 204, 254, 225, 245, 225, 252, 143, 206, 179,
-197, 208, 143, 206, 182, 187, 169, 226, 173, 143, 206, 193, 200, 233, 226, 176,
-226, 179, 143, 206, 205, 226, 181, 143, 206, 209, 226, 187, 196, 190, 189, 226,
-226, 190, 143, 206, 222, 143, 206, 228, 226, 197, 143, 206, 234, 143, 206, 239,
-143, 206, 243, 143, 206, 248, 143, 206, 253, 143, 207, 163, 143, 207, 168, 226,
-208, 226, 211, 143, 207, 176, 143, 207, 179, 143, 207, 182, 143, 207, 186, 226,
-218, 143, 207, 189, 143, 207, 192, 143, 207, 195, 182, 235, 192, 208, 186, 189,
-226, 230, 143, 207, 212, 181, 206, 203, 164, 185, 220, 143, 207, 225, 143, 207,
-228, 143, 207, 234, 200, 163, 226, 239, 226, 238, 200, 234, 143, 207, 244, 202,
-203, 143, 207, 252, 143, 208, 161, 226, 252, 200, 216, 227, 162, 143, 208, 173,
-176, 235, 143, 208, 185, 143, 208, 188, 143, 208, 190, 143, 208, 191, 143, 208,
-196, 143, 208, 200, 143, 208, 203, 143, 208, 207, 143, 208, 211, 227, 175, 190,
-205, 143, 208, 220, 143, 208, 223, 227, 180, 143, 208, 229, 143, 208, 235, 143,
-208, 238, 143, 208, 242, 143, 208, 244, 143, 208, 249, 143, 208, 252, 199, 233,
-190, 206, 176, 220, 143, 209, 172, 143, 209, 176, 143, 209, 178, 143, 209, 181,
-227, 202, 227, 203, 143, 209, 192, 178, 186, 143, 209, 198, 190, 247, 143, 209,
-206, 143, 209, 208, 143, 209, 211, 143, 209, 216, 143, 209, 219, 227, 221, 143,
-209, 223, 227, 227, 143, 209, 229, 227, 234, 227, 237, 143, 209, 234, 143, 209,
-239, 143, 209, 242, 181, 232, 143, 209, 244, 227, 250, 227, 252, 227, 247, 143,
-210, 163, 143, 210, 167, 195, 222, 228, 184, 228, 170, 228, 172, 143, 210, 180,
-143, 210, 182, 228, 176, 143, 210, 189, 143, 210, 191, 143, 210, 196, 200, 207,
-228, 189, 143, 210, 207, 198, 198, 143, 210, 212, 143, 210, 218, 143, 210, 224,
-228, 194, 143, 210, 231, 143, 210, 233, 143, 210, 237, 228, 213, 143, 210, 244,
-228, 216, 143, 210, 254, 143, 211, 164, 202, 198, 143, 211, 171, 143, 211, 173,
-206, 179, 143, 211, 176, 228, 234, 228, 236, 143, 211, 184, 143, 211, 187, 228,
-245, 228, 246, 143, 211, 199, 228, 250, 181, 234, 143, 211, 205, 143, 211, 209,
-229, 162, 143, 211, 215, 186, 217, 186, 176, 193, 200, 229, 174, 143, 211, 230,
-229, 179, 229, 177, 143, 211, 238, 143, 211, 243, 143, 211, 249, 143, 211, 252,
-229, 194, 188, 250, 143, 212, 166, 143, 212, 169, 143, 212, 174, 143, 212, 177,
-229, 206, 143, 212, 184, 143, 212, 187, 143, 212, 179, 229, 208, 143, 212, 194,
-229, 213, 203, 165, 229, 220, 143, 212, 206, 193, 161, 191, 165, 229, 229, 229,
-234, 143, 212, 221, 229, 239, 143, 212, 226, 143, 212, 229, 229, 251, 180, 204,
-143, 212, 240, 230, 163, 230, 169, 143, 212, 250, 143, 212, 254, 200, 237, 230,
-176, 230, 181, 143, 213, 171, 143, 213, 174, 143, 213, 178, 230, 192, 143, 213,
-183, 143, 213, 185, 143, 213, 187, 143, 213, 190, 143, 213, 194, 230, 203, 185,
-205, 143, 213, 203, 204, 215, 230, 212, 143, 213, 216, 204, 237, 143, 213, 226,
-230, 216, 192, 187, 143, 213, 228, 143, 213, 231, 191, 166, 143, 213, 234, 207,
-190, 190, 211, 184, 212, 143, 213, 241, 143, 213, 242, 176, 223, 143, 213, 245,
-143, 213, 250, 184, 213, 143, 213, 253, 182, 187, 187, 233, 143, 214, 170, 143,
-214, 175, 143, 214, 178, 196, 177, 143, 214, 183, 201, 229, 231, 181, 143, 214,
-193, 231, 171, 194, 220, 231, 174, 231, 178, 231, 177, 143, 214, 209, 231, 187,
-231, 190, 231, 193, 143, 214, 220, 143, 214, 224, 143, 214, 226, 143, 214, 231,
-143, 214, 236, 218, 170, 143, 214, 240, 143, 214, 244, 143, 214, 247, 143, 214,
-248, 231, 217, 143, 215, 161, 143, 215, 165, 143, 215, 167, 231, 226, 143, 215,
-171, 231, 232, 143, 215, 180, 143, 215, 184, 231, 236, 143, 215, 195, 203, 167,
-178, 234, 143, 215, 207, 143, 215, 209, 143, 215, 212, 143, 215, 216, 231, 249,
-231, 247, 183, 212, 232, 173, 143, 215, 233, 143, 215, 234, 195, 227, 232, 166,
-183, 213, 143, 215, 227, 143, 215, 253, 178, 174, 232, 174, 143, 216, 168, 143,
-216, 174, 143, 216, 176, 205, 233, 232, 207, 143, 216, 183, 143, 216, 187, 186,
-218, 143, 216, 191, 232, 203, 143, 216, 196, 143, 216, 198, 143, 216, 201, 232,
-206, 232, 212, 232, 226, 143, 216, 207, 143, 216, 212, 143, 216, 217, 198, 161,
-232, 211, 232, 216, 143, 216, 232, 190, 213, 143, 216, 236, 232, 231, 143, 216,
-240, 143, 216, 244, 143, 216, 247, 143, 216, 251, 143, 216, 254, 143, 217, 162,
-143, 217, 166, 143, 217, 171, 232, 209, 143, 217, 178, 177, 182, 143, 217, 183,
-143, 217, 188, 202, 195, 232, 254, 143, 217, 197, 143, 217, 201, 207, 207, 233,
-177, 143, 217, 216, 143, 217, 220, 177, 242, 143, 217, 228, 204, 244, 143, 217,
-232, 207, 206, 143, 217, 242, 233, 185, 143, 217, 247, 200, 205, 143, 217, 252,
-233, 193, 233, 190, 221, 177, 143, 218, 174, 205, 246, 143, 218, 178, 143, 218,
-183, 233, 200, 143, 218, 188, 143, 218, 193, 195, 238, 143, 218, 200, 143, 218,
-237, 233, 206, 143, 218, 210, 233, 219, 143, 218, 218, 143, 218, 222, 233, 217,
-233, 220, 233, 221, 233, 222, 194, 253, 203, 170, 233, 235, 195, 216, 143, 218,
-254, 143, 219, 162, 143, 219, 166, 143, 219, 172, 143, 219, 174, 233, 251, 143,
-219, 177, 233, 253, 233, 247, 234, 167, 143, 219, 192, 143, 219, 196, 234, 165,
-143, 219, 203, 205, 230, 234, 175, 143, 219, 214, 143, 219, 217, 143, 219, 222,
-143, 219, 226, 234, 187, 143, 219, 232, 143, 219, 237, 234, 192, 143, 219, 248,
-143, 219, 250, 234, 197, 143, 220, 164, 222, 167, 179, 185, 185, 213, 234, 206,
-234, 210, 182, 222, 194, 222, 194, 181, 143, 220, 190, 143, 220, 192, 184, 211,
-143, 220, 195, 143, 220, 197, 234, 227, 143, 220, 206, 234, 235, 234, 236, 234,
-233, 143, 220, 214, 179, 236, 143, 220, 222, 234, 243, 143, 220, 228, 143, 220,
-233, 234, 247, 143, 220, 240, 143, 220, 243, 235, 162, 143, 220, 250, 143, 220,
-254, 202, 164, 143, 221, 166, 179, 208, 143, 221, 173, 235, 178, 235, 180, 179,
-209, 235, 185, 191, 168, 143, 221, 189, 143, 221, 193, 143, 221, 197, 143, 221,
-199, 235, 194, 235, 196, 143, 221, 210, 191, 199, 143, 221, 217, 186, 190, 235,
-199, 143, 221, 229, 181, 205, 143, 221, 235, 235, 209, 143, 221, 243, 143, 221,
-248, 235, 216, 198, 201, 143, 222, 162, 235, 219, 180, 210, 207, 192, 235, 227,
-235, 221, 143, 222, 180, 143, 222, 183, 143, 222, 191, 235, 226, 143, 222, 189,
-235, 245, 235, 240, 235, 244, 143, 222, 201, 143, 222, 202, 201, 232, 183, 217,
-181, 196, 143, 222, 213, 218, 206, 143, 222, 221, 143, 222, 224, 195, 171, 236,
-175, 143, 222, 233, 236, 181, 190, 221, 208, 174, 143, 222, 250, 236, 186, 203,
-198, 236, 194, 185, 215, 192, 213, 236, 202, 178, 236, 194, 177, 143, 223, 178,
-199, 229, 188, 193, 143, 223, 187, 143, 223, 191, 143, 223, 194, 236, 219, 192,
-214, 143, 223, 201, 143, 223, 202, 177, 219, 143, 223, 209, 143, 223, 211, 143,
-223, 214, 143, 223, 218, 143, 223, 222, 143, 223, 227, 143, 223, 230, 236, 240,
-236, 238, 143, 223, 242, 236, 245, 236, 244, 143, 223, 250, 236, 247, 237, 169,
-236, 253, 143, 224, 171, 236, 254, 143, 224, 177, 143, 224, 181, 143, 224, 184,
-189, 179, 237, 175, 237, 179, 143, 224, 198, 237, 186, 191, 200, 143, 224, 209,
-143, 224, 212, 188, 214, 143, 224, 219, 198, 240, 237, 199, 143, 224, 225, 143,
-224, 230, 237, 210, 143, 224, 235, 143, 224, 239, 206, 216, 143, 224, 248, 237,
-217, 237, 219, 143, 225, 166, 143, 225, 170, 191, 201, 143, 225, 177, 237, 231,
-202, 213, 203, 248, 183, 222, 237, 233, 143, 225, 195, 143, 225, 197, 237, 254,
-143, 225, 203, 143, 225, 206, 237, 248, 194, 164, 143, 225, 212, 143, 225, 216,
-238, 167, 238, 166, 198, 187, 143, 225, 223, 143, 225, 226, 238, 175, 206, 203,
-237, 238, 205, 184, 143, 225, 241, 143, 225, 245, 238, 184, 143, 225, 251, 143,
-226, 163, 143, 226, 173, 143, 226, 169, 201, 244, 143, 226, 178, 143, 226, 179,
-143, 226, 185, 238, 192, 143, 226, 193, 143, 226, 199, 143, 226, 203, 143, 226,
-209, 143, 226, 212, 188, 242, 143, 226, 220, 189, 183, 185, 243, 143, 226, 228,
-238, 204, 143, 226, 237, 143, 226, 240, 238, 208, 238, 211, 143, 226, 254, 238,
-216, 143, 227, 164, 191, 203, 182, 252, 143, 227, 179, 143, 227, 182, 143, 227,
-187, 143, 227, 193, 143, 227, 198, 143, 227, 203, 143, 227, 207, 143, 227, 213,
-197, 180, 143, 227, 223, 143, 227, 226, 200, 173, 143, 227, 236, 143, 227, 242,
-189, 198, 143, 227, 251, 143, 227, 254, 143, 228, 164, 143, 228, 169, 238, 248,
-143, 228, 181, 143, 228, 188, 143, 228, 193, 143, 228, 200, 143, 228, 205, 181,
-248, 143, 228, 212, 143, 228, 214, 191, 238, 239, 162, 207, 163, 143, 228, 230,
-238, 253, 143, 228, 235, 143, 228, 241, 143, 228, 243, 239, 171, 143, 229, 161,
-143, 229, 167, 143, 229, 172, 143, 229, 176, 143, 229, 181, 143, 229, 183, 143,
-229, 188, 143, 229, 195, 239, 178, 182, 192, 143, 229, 207, 143, 229, 212, 143,
-229, 217, 143, 229, 222, 239, 197, 239, 195, 239, 196, 143, 229, 231, 143, 229,
-236, 143, 229, 238, 143, 229, 241, 239, 206, 239, 209, 239, 216, 196, 185, 239,
-217, 143, 230, 164, 239, 221, 239, 224, 143, 230, 173, 143, 230, 176, 239, 234,
-239, 235, 198, 174, 239, 243, 201, 236, 143, 230, 201, 143, 230, 203, 193, 203,
-239, 251, 143, 230, 214, 143, 230, 217, 240, 165, 198, 171, 143, 230, 224, 231,
-161, 240, 168, 143, 230, 233, 143, 230, 237, 143, 230, 240, 191, 253, 143, 230,
-242, 240, 186, 143, 230, 249, 143, 230, 250, 206, 237, 188, 251, 206, 238, 240,
-195, 143, 231, 167, 240, 199, 240, 201, 240, 205, 192, 196, 240, 208, 240, 211,
-240, 215, 143, 231, 191, 240, 217, 240, 223, 143, 231, 199, 240, 228, 202, 220,
-143, 231, 210, 240, 231, 143, 231, 223, 143, 231, 228, 143, 231, 235, 240, 236,
-143, 231, 240, 202, 199, 240, 243, 143, 231, 249, 143, 231, 252, 143, 232, 161,
-143, 232, 167, 143, 232, 170, 179, 220, 180, 234, 143, 232, 180, 143, 232, 185,
-201, 247, 143, 232, 190, 143, 232, 195, 143, 232, 199, 200, 244, 143, 232, 202,
-200, 211, 187, 244, 143, 232, 209, 143, 232, 211, 143, 232, 216, 143, 232, 220,
-143, 232, 223, 143, 232, 230, 241, 189, 241, 190, 143, 232, 242, 188, 243, 241,
-198, 143, 232, 251, 143, 233, 162, 194, 204, 195, 243, 143, 233, 170, 143, 233,
-173, 241, 209, 241, 211, 241, 215, 241, 214, 241, 217, 143, 233, 194, 143, 233,
-197, 241, 219, 143, 233, 204, 143, 233, 207, 241, 225, 241, 229, 241, 233, 185,
-252, 143, 233, 218, 241, 238, 143, 233, 228, 143, 233, 231, 143, 233, 236, 143,
-233, 240, 241, 249, 143, 233, 247, 143, 233, 254, 143, 234, 167, 242, 163, 242,
-166, 143, 234, 178, 143, 234, 182, 179, 161, 143, 234, 187, 143, 234, 189, 143,
-234, 194, 143, 234, 200, 143, 234, 205, 143, 234, 209, 143, 234, 215, 242, 184,
-143, 234, 223, 143, 234, 226, 143, 234, 230, 143, 234, 234, 242, 196, 143, 234,
-242, 194, 228, 143, 234, 247, 143, 234, 251, 143, 235, 161, 242, 218, 143, 235,
-168, 143, 235, 172, 143, 235, 177, 201, 201, 143, 235, 186, 143, 235, 188, 143,
-235, 194, 143, 235, 200, 143, 235, 205, 143, 235, 211, 242, 233, 196, 187, 242,
-236, 143, 235, 222, 178, 170, 143, 235, 225, 242, 245, 143, 235, 229, 143, 235,
-234, 242, 247, 243, 165, 177, 173, 143, 235, 248, 143, 235, 252, 143, 236, 163,
-143, 236, 167, 143, 236, 173, 143, 236, 175, 243, 170, 143, 236, 180, 143, 236,
-183, 143, 236, 186, 243, 186, 143, 236, 193, 143, 236, 198, 143, 236, 202, 243,
-191, 143, 236, 207, 143, 236, 210, 243, 193, 243, 195, 188, 175, 243, 200, 243,
-203, 206, 219, 243, 207, 143, 236, 238, 221, 224, 143, 236, 242, 185, 245, 243,
-217, 143, 236, 247, 143, 236, 252, 243, 228, 243, 231, 143, 237, 168, 143, 237,
-175, 143, 237, 178, 143, 237, 182, 201, 161, 143, 237, 194, 240, 237, 143, 237,
-202, 243, 245, 143, 237, 210, 143, 237, 214, 206, 182, 143, 237, 222, 143, 237,
-224, 161, 170, 161, 220, 163, 181, 161, 169, 163, 201, 163, 211, 161, 207, 163,
-231, 163, 241, 161, 208, 142, 165, 142, 175, 142, 185, 142, 195, 142, 205, 142,
-215, 161, 177
-            });
-
-        super.setUp();
-    }
-
-    @Override
-    public void test_CodecDynamic () throws CharacterCodingException {
-        encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
-        decoder.onMalformedInput(CodingErrorAction.REPORT);
-        CharBuffer inputCB = CharBuffer.allocate(65536);
-        for (int code = 32; code <= 65533; code ++) {
-            if ((encoder.canEncode((char) code))
-                    && (code != 165) && (code != 8254) && (code != 63599)) {
-                inputCB.put((char) code);
-            }
-        }
-        inputCB.rewind();
-        ByteBuffer intermediateBB = encoder.encode(inputCB);
-        inputCB.rewind();
-        intermediateBB.rewind();
-        CharBuffer outputCB = decoder.decode(intermediateBB);
-        outputCB.rewind();
-        assertEqualCBs("decode(encode(A)) must be identical with A!",
-                inputCB, outputCB);
-    }
-
-}
diff --git a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_ISO_2022_JP.java b/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_ISO_2022_JP.java
index b789ce3..e8790ea 100644
--- a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_ISO_2022_JP.java
+++ b/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_ISO_2022_JP.java
@@ -18,364 +18,16 @@
 import java.nio.charset.CharacterCodingException;
 
 public class OldCharset_MultiByte_ISO_2022_JP extends OldCharset_AbstractTest {
-
-    @Override
-    protected void setUp() throws Exception {
-        charsetName = "ISO-2022-JP";
-
-        testChars = theseChars(new int[]{
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
-96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
-162, 163, 165, 167, 168, 172, 176, 177, 180, 182, 215, 247, 913, 914, 924, 934,
-945, 955, 965, 1025, 1040, 1050, 1060, 1070, 1080, 1090, 1100, 8208, 8220, 8230, 8240, 8251,
-8451, 8491, 8592, 8658, 8704, 8715, 8730, 8743, 8756, 8786, 8800, 8810, 8834, 8869, 8978, 9472,
-9484, 9495, 9507, 9519, 9531, 9547, 9632, 9650, 9660, 9670, 9711, 9733, 9792, 9834, 12288, 12298,
-12308, 12353, 12363, 12373, 12383, 12393, 12403, 12413, 12423, 12433, 12443, 12453, 12463, 12473, 12483, 12493,
-12503, 12513, 12523, 12533, 19968, 19978, 19988, 19998, 20010, 20022, 20034, 20045, 20055, 20066, 20081, 20094,
-20104, 20114, 20124, 20134, 20144, 20154, 20164, 20174, 20184, 20195, 20205, 20215, 20225, 20237, 20250, 20271,
-20282, 20294, 20304, 20314, 20329, 20339, 20351, 20363, 20374, 20384, 20395, 20405, 20415, 20426, 20436, 20447,
-20462, 20472, 20485, 20495, 20505, 20515, 20525, 20537, 20547, 20559, 20570, 20581, 20594, 20605, 20621, 20632,
-20652, 20663, 20674, 20685, 20698, 20709, 20725, 20736, 20754, 20767, 20778, 20791, 20801, 20811, 20826, 20837,
-20849, 20860, 20870, 20880, 20896, 20906, 20916, 20932, 20950, 20960, 20970, 20981, 20992, 21002, 21012, 21028,
-21038, 21048, 21059, 21069, 21083, 21093, 21103, 21117, 21127, 21137, 21147, 21161, 21172, 21182, 21193, 21205,
-21215, 21234, 21246, 21256, 21269, 21280, 21290, 21304, 21315, 21325, 21335, 21350, 21360, 21371, 21398, 21408,
-21421, 21435, 21448, 21460, 21471, 21481, 21491, 21505, 21515, 21531, 21542, 21558, 21568, 21578, 21599, 21610,
-21621, 21632, 21643, 21666, 21676, 21688, 21698, 21720, 21730, 21741, 21754, 21764, 21775, 21806, 21816, 21828,
-21839, 21852, 21883, 21895, 21912, 21927, 21942, 21956, 21972, 21983, 22007, 22022, 22036, 22057, 22068, 22082,
-22092, 22107, 22120, 22132, 22144, 22154, 22164, 22176, 22190, 22204, 22216, 22227, 22238, 22254, 22265, 22275,
-22285, 22296, 22310, 22320, 22331, 22343, 22353, 22369, 22399, 22409, 22419, 22432, 22442, 22464, 22475, 22486,
-22496, 22516, 22528, 22538, 22549, 22561, 22575, 22586, 22602, 22612, 22622, 22633, 22645, 22659, 22675, 22687,
-22699, 22712, 22725, 22737, 22748, 22763, 22775, 22786, 22799, 22809, 22821, 22833, 22846, 22856, 22868, 22880,
-22890, 22900, 22913, 22925, 22937, 22947, 22962, 22974, 22985, 22995, 23013, 23030, 23041, 23057, 23068, 23081,
-23093, 23104, 23130, 23142, 23167, 23186, 23228, 23241, 23254, 23265, 23290, 23305, 23318, 23330, 23340, 23350,
-23360, 23376, 23386, 23396, 23408, 23418, 23429, 23439, 23449, 23459, 23470, 23480, 23490, 23500, 23515, 23525,
-23536, 23546, 23556, 23566, 23578, 23588, 23601, 23611, 23621, 23631, 23646, 23660, 23670, 23692, 23713, 23723,
-23734, 23749, 23769, 23784, 23798, 23815, 23825, 23835, 23849, 23883, 23900, 23913, 23923, 23938, 23948, 23965,
-23980, 23991, 24009, 24019, 24029, 24039, 24049, 24059, 24070, 24081, 24091, 24101, 24111, 24125, 24135, 24148,
-24159, 24178, 24188, 24199, 24213, 24224, 24235, 24245, 24257, 24271, 24282, 24296, 24307, 24318, 24329, 24339,
-24351, 24361, 24373, 24385, 24396, 24406, 24417, 24427, 24439, 24449, 24459, 24471, 24481, 24493, 24505, 24515,
-24525, 24535, 24548, 24560, 24571, 24590, 24601, 24613, 24623, 24634, 24646, 24656, 24666, 24676, 24687, 24705,
-24715, 24726, 24736, 24746, 24756, 24773, 24785, 24796, 24807, 24817, 24827, 24838, 24853, 24863, 24876, 24892,
-24903, 24915, 24925, 24935, 24945, 24958, 24970, 24980, 24996, 25006, 25018, 25030, 25040, 25059, 25074, 25084,
-25096, 25106, 25117, 25130, 25140, 25151, 25161, 25171, 25182, 25192, 25206, 25216, 25226, 25236, 25246, 25259,
-25269, 25282, 25292, 25303, 25313, 25324, 25334, 25345, 25356, 25369, 25383, 25402, 25417, 25429, 25447, 25458,
-25472, 25484, 25494, 25504, 25514, 25524, 25534, 25545, 25558, 25569, 25582, 25594, 25606, 25619, 25638, 25652,
-25662, 25678, 25688, 25703, 25718, 25731, 25746, 25758, 25769, 25785, 25797, 25810, 25824, 25836, 25846, 25856,
-25880, 25891, 25903, 25913, 25925, 25935, 25945, 25955, 25968, 25986, 25996, 26007, 26017, 26027, 26039, 26049,
-26059, 26071, 26081, 26092, 26106, 26118, 26131, 26143, 26157, 26172, 26185, 26205, 26215, 26228, 26241, 26254,
-26264, 26274, 26286, 26296, 26308, 26326, 26336, 26352, 26364, 26376, 26388, 26398, 26408, 26420, 26431, 26441,
-26451, 26462, 26474, 26485, 26495, 26505, 26517, 26528, 26543, 26553, 26564, 26574, 26584, 26594, 26604, 26619,
-26643, 26654, 26665, 26676, 26688, 26701, 26713, 26723, 26740, 26750, 26765, 26775, 26786, 26797, 26809, 26820,
-26834, 26847, 26862, 26873, 26884, 26894, 26905, 26915, 26928, 26941, 26954, 26964, 26974, 26986, 26996, 27006,
-27018, 27028, 27040, 27054, 27067, 27079, 27091, 27101, 27111, 27122, 27133, 27146, 27156, 27166, 27177, 27189,
-27204, 27224, 27234, 27250, 27263, 27277, 27287, 27298, 27308, 27320, 27330, 27345, 27355, 27368, 27386, 27396,
-27410, 27421, 27431, 27442, 27453, 27463, 27475, 27487, 27497, 27507, 27519, 27529, 27541, 27556, 27567, 27578,
-27589, 27602, 27615, 27627, 27656, 27667, 27683, 27700, 27710, 27726, 27738, 27752, 27762, 27773, 27784, 27794,
-27809, 27819, 27832, 27844, 27859, 27869, 27880, 27891, 27915, 27927, 27941, 27954, 27965, 27993, 28003, 28014,
-28024, 28037, 28051, 28079, 28092, 28102, 28113, 28126, 28136, 28147, 28165, 28179, 28189, 28201, 28216, 28227,
-28237, 28248, 28263, 28274, 28286, 28300, 28310, 28322, 28335, 28346, 28356, 28369, 28381, 28396, 28407, 28417,
-28431, 28448, 28459, 28472, 28485, 28500, 28511, 28525, 28536, 28546, 28558, 28577, 28593, 28608, 28628, 28639,
-28651, 28662, 28673, 28683, 28693, 28703, 28716, 28734, 28748, 28760, 28771, 28783, 28796, 28809, 28825, 28844,
-28856, 28872, 28889, 28913, 28925, 28937, 28948, 28961, 28982, 29001, 29013, 29026, 29036, 29053, 29064, 29076,
-29087, 29100, 29113, 29123, 29134, 29151, 29164, 29177, 29190, 29200, 29211, 29224, 29234, 29244, 29254, 29266,
-29277, 29287, 29298, 29309, 29319, 29330, 29344, 29356, 29366, 29378, 29390, 29401, 29417, 29431, 29450, 29462,
-29477, 29487, 29502, 29518, 29539, 29552, 29562, 29572, 29590, 29609, 29619, 29632, 29642, 29662, 29674, 29688,
-29699, 29730, 29746, 29759, 29781, 29791, 29801, 29811, 29822, 29835, 29854, 29872, 29885, 29898, 29908, 29920,
-29934, 29944, 29955, 29965, 29976, 29987, 30000, 30010, 30020, 30031, 30041, 30052, 30064, 30079, 30089, 30100,
-30115, 30129, 30140, 30151, 30162, 30174, 30185, 30195, 30206, 30217, 30239, 30256, 30267, 30278, 30290, 30300,
-30311, 30322, 30332, 30342, 30352, 30362, 30382, 30392, 30402, 30413, 30423, 30433, 30446, 30456, 30468, 30491,
-30501, 30519, 30535, 30554, 30565, 30585, 30603, 30622, 30636, 30646, 30663, 30679, 30690, 30701, 30716, 30732,
-30752, 30770, 30783, 30813, 30827, 30844, 30854, 30865, 30883, 30895, 30906, 30917, 30928, 30938, 30951, 30964,
-30977, 30990, 31001, 31014, 31034, 31047, 31059, 31069, 31080, 31095, 31105, 31117, 31133, 31143, 31155, 31165,
-31177, 31189, 31199, 31209, 31227, 31240, 31252, 31263, 31278, 31291, 31302, 31312, 31329, 31339, 31350, 31361,
-31378, 31391, 31401, 31414, 31427, 31437, 31449, 31459, 31469, 31480, 31490, 31503, 31513, 31525, 31539, 31557,
-31567, 31581, 31591, 31601, 31622, 31634, 31644, 31658, 31668, 31680, 31691, 31709, 31721, 31731, 31744, 31757,
-31767, 31777, 31787, 31799, 31811, 31821, 31832, 31844, 31859, 31870, 31881, 31893, 31903, 31915, 31929, 31941,
-31954, 31964, 31975, 31986, 31998, 32010, 32020, 32032, 32043, 32053, 32063, 32075, 32086, 32097, 32110, 32121,
-32137, 32147, 32159, 32171, 32181, 32191, 32202, 32213, 32224, 32236, 32251, 32261, 32274, 32286, 32299, 32309,
-32321, 32331, 32341, 32358, 32368, 32379, 32392, 32402, 32412, 32566, 32581, 32592, 32607, 32617, 32629, 32642,
-32652, 32666, 32676, 32686, 32696, 32709, 32722, 32736, 32747, 32761, 32771, 32784, 32796, 32808, 32819, 32829,
-32842, 32854, 32865, 32879, 32889, 32900, 32915, 32925, 32937, 32948, 32963, 32974, 32985, 32996, 33007, 33020,
-33030, 33050, 33065, 33075, 33086, 33099, 33109, 33119, 33131, 33144, 33154, 33167, 33178, 33188, 33200, 33210,
-33222, 33233, 33247, 33258, 33268, 33278, 33288, 33298, 33308, 33321, 33331, 33344, 33368, 33378, 33390, 33400,
-33419, 33433, 33445, 33455, 33465, 33477, 33489, 33499, 33509, 33521, 33531, 33541, 33558, 33571, 33583, 33593,
-33605, 33615, 33651, 33669, 33683, 33694, 33704, 33717, 33729, 33740, 33750, 33760, 33771, 33783, 33795, 33805,
-33824, 33834, 33845, 33862, 33879, 33889, 33899, 33909, 33922, 33936, 33948, 33965, 33976, 33988, 34000, 34010,
-34028, 34044, 34054, 34065, 34079, 34092, 34109, 34120, 34133, 34147, 34157, 34167, 34180, 34192, 34203, 34214,
-34233, 34249, 34261, 34276, 34295, 34306, 34323, 34338, 34349, 34367, 34381, 34394, 34407, 34417, 34427, 34442,
-34453, 34467, 34479, 34500, 34510, 34521, 34532, 34542, 34552, 34562, 34573, 34584, 34597, 34612, 34623, 34633,
-34643, 34655, 34666, 34676, 34687, 34701, 34719, 34731, 34746, 34756, 34768, 34784, 34799, 34809, 34821, 34831,
-34849, 34865, 34875, 34886, 34898, 34909, 34920, 34930, 34941, 34952, 34962, 34974, 34987, 34997, 35007, 35023,
-35033, 35048, 35058, 35068, 35079, 35090, 35101, 35114, 35126, 35137, 35148, 35158, 35168, 35178, 35188, 35198,
-35208, 35219, 35233, 35244, 35258, 35282, 35292, 35302, 35316, 35328, 35338, 35350, 35363, 35373, 35386, 35398,
-35408, 35419, 35430, 35440, 35452, 35463, 35473, 35486, 35496, 35506, 35516, 35527, 35538, 35548, 35558, 35569,
-35582, 35596, 35606, 35616, 35627, 35641, 35657, 35670, 35686, 35696, 35709, 35722, 35734, 35895, 35905, 35916,
-35930, 35946, 35960, 35970, 35980, 35992, 36002, 36012, 36022, 36032, 36042, 36058, 36068, 36090, 36100, 36111,
-36196, 36208, 36225, 36249, 36259, 36275, 36286, 36299, 36310, 36321, 36331, 36341, 36351, 36361, 36381, 36394,
-36404, 36418, 36428, 36441, 36451, 36466, 36476, 36487, 36497, 36513, 36523, 36542, 36552, 36562, 36575, 36587,
-36600, 36611, 36626, 36636, 36646, 36659, 36670, 36681, 36695, 36705, 36763, 36775, 36785, 36795, 36805, 36817,
-36834, 36845, 36855, 36865, 36875, 36885, 36895, 36910, 36920, 36930, 36941, 36952, 36963, 36973, 36983, 36993,
-37007, 37027, 37039, 37057, 37070, 37083, 37096, 37109, 37122, 37138, 37165, 37193, 37204, 37218, 37228, 37239,
-37250, 37261, 37271, 37282, 37295, 37306, 37318, 37328, 37339, 37350, 37365, 37375, 37389, 37406, 37417, 37428,
-37439, 37449, 37463, 37474, 37489, 37502, 37521, 37531, 37549, 37559, 37583, 37604, 37618, 37628, 37638, 37648,
-37658, 37670, 37682, 37700, 37716, 37728, 37740, 37756, 37772, 37782, 37799, 37817, 37827, 37840, 37853, 37864,
-37891, 37904, 37914, 37931, 37941, 37953, 37969, 37979, 37994, 38005, 38015, 38263, 38274, 38287, 38297, 38307,
-38317, 38329, 38339, 38349, 38360, 38370, 38428, 38440, 38450, 38463, 38475, 38491, 38501, 38512, 38522, 38533,
-38543, 38553, 38563, 38576, 38587, 38597, 38609, 38619, 38632, 38642, 38656, 38666, 38678, 38692, 38704, 38717,
-38728, 38738, 38748, 38758, 38769, 38780, 38790, 38800, 38812, 38822, 38835, 38851, 38867, 38893, 38907, 38917,
-38927, 38938, 38948, 38964, 38982, 38996, 39006, 39019, 39080, 39094, 39107, 39131, 39145, 39156, 39166, 39177,
-39187, 39197, 39208, 39229, 39241, 39253, 39318, 39333, 39347, 39361, 39376, 39387, 39405, 39416, 39429, 39439,
-39449, 39464, 39479, 39490, 39501, 39511, 39522, 39592, 39608, 39620, 39631, 39646, 39658, 39668, 39686, 39704,
-39714, 39726, 39739, 39749, 39759, 39770, 39791, 39811, 39822, 39839, 39850, 39860, 39872, 39882, 39892, 39905,
-39920, 39940, 39952, 39963, 39973, 39983, 39993, 40006, 40018, 40032, 40054, 40165, 40176, 40195, 40206, 40219,
-40230, 40251, 40262, 40272, 40284, 40300, 40314, 40327, 40346, 40356, 40367, 40378, 40388, 40399, 40409, 40422,
-40434, 40445, 40474, 40565, 40575, 40587, 40597, 40607, 40617, 40632, 40644, 40654, 40664, 40677, 40687, 40697,
-40711, 40723, 40736, 40748, 40763, 40778, 40788, 40799, 40810, 40822, 40845, 40860, 65281, 65291, 65301, 65311,
-65321, 65331, 65341, 65351, 65361, 65371, 65381, 65391, 65401, 65411, 65421, 65431, 65507
-            });
-
-        testBytes = theseBytes(new int[]{
-32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
-48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
-64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
-80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
-96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
-27, 36, 66, 33, 113, 33, 114, 27, 40, 74, 92, 27, 36, 66, 33, 120,
-33, 47, 34, 76, 33, 107, 33, 94, 33, 45, 34, 121, 33, 95, 33, 96,
-38, 33, 38, 34, 38, 44, 38, 53, 38, 65, 38, 75, 38, 84, 39, 39,
-39, 33, 39, 44, 39, 54, 39, 64, 39, 90, 39, 100, 39, 110, 33, 62,
-33, 72, 33, 68, 34, 115, 34, 40, 33, 110, 34, 114, 34, 43, 34, 77,
-34, 79, 34, 59, 34, 101, 34, 74, 33, 104, 34, 98, 33, 98, 34, 99,
-34, 62, 34, 93, 34, 94, 40, 33, 40, 35, 40, 49, 40, 50, 40, 56,
-40, 53, 40, 54, 34, 35, 34, 37, 34, 39, 34, 33, 34, 126, 33, 122,
-33, 106, 34, 118, 33, 33, 33, 84, 33, 76, 36, 33, 36, 43, 36, 53,
-36, 63, 36, 73, 36, 83, 36, 93, 36, 103, 36, 113, 33, 43, 37, 37,
-37, 47, 37, 57, 37, 67, 37, 77, 37, 87, 37, 97, 37, 107, 37, 117,
-48, 108, 62, 101, 51, 110, 62, 103, 80, 36, 80, 38, 80, 41, 70, 99,
-62, 104, 86, 38, 77, 112, 52, 37, 77, 61, 56, 95, 48, 33, 75, 114,
-80, 55, 63, 77, 80, 60, 80, 58, 73, 85, 66, 101, 80, 65, 80, 67,
-52, 107, 56, 96, 50, 113, 71, 108, 59, 71, 67, 34, 58, 52, 80, 69,
-80, 80, 50, 66, 59, 72, 78, 99, 80, 85, 54, 34, 85, 37, 63, 47,
-74, 88, 61, 83, 80, 87, 80, 88, 61, 36, 74, 112, 80, 102, 96, 71,
-56, 117, 74, 111, 79, 65, 55, 112, 80, 112, 74, 80, 80, 118, 55, 114,
-60, 69, 53, 54, 75, 53, 59, 49, 58, 69, 61, 125, 81, 36, 70, 47,
-78, 61, 81, 39, 81, 44, 53, 55, 60, 116, 61, 126, 77, 37, 81, 54,
-48, 116, 57, 110, 69, 94, 70, 126, 54, 38, 55, 115, 49, 95, 102, 110,
-52, 39, 81, 81, 58, 99, 64, 40, 82, 69, 81, 92, 70, 100, 81, 97,
-69, 97, 52, 41, 81, 101, 72, 61, 81, 105, 55, 116, 68, 102, 65, 48,
-57, 100, 71, 109, 73, 123, 81, 119, 55, 96, 81, 125, 78, 79, 61, 117,
-79, 43, 51, 47, 74, 89, 70, 48, 74, 103, 55, 46, 56, 123, 82, 51,
-82, 56, 62, 34, 72, 91, 82, 62, 64, 105, 82, 68, 70, 110, 55, 53,
-48, 117, 82, 74, 82, 77, 82, 78, 49, 94, 53, 110, 75, 116, 61, 71,
-82, 87, 67, 33, 49, 38, 82, 94, 49, 37, 55, 47, 72, 93, 82, 101,
-82, 96, 57, 112, 82, 108, 60, 118, 82, 106, 82, 114, 58, 112, 82, 120,
-82, 123, 82, 121, 83, 34, 83, 38, 83, 47, 83, 45, 83, 46, 49, 52,
-83, 41, 83, 52, 83, 57, 66, 111, 76, 100, 83, 53, 83, 65, 83, 73,
-83, 67, 55, 118, 49, 68, 83, 78, 83, 81, 83, 77, 83, 83, 67, 50,
-83, 82, 50, 94, 83, 92, 49, 61, 65, 57, 51, 122, 52, 111, 74, 46,
-83, 102, 83, 103, 83, 105, 83, 104, 83, 108, 83, 112, 83, 116, 83, 119,
-50, 115, 83, 121, 83, 122, 74, 96, 84, 35, 84, 37, 84, 41, 67, 79,
-84, 45, 54, 81, 57, 35, 84, 51, 84, 52, 84, 53, 84, 54, 84, 55,
-84, 58, 84, 49, 75, 100, 84, 66, 73, 86, 62, 125, 75, 89, 84, 65,
-66, 68, 84, 72, 116, 33, 58, 102, 50, 116, 69, 99, 58, 73, 49, 118,
-63, 80, 54, 45, 74, 104, 84, 82, 84, 83, 84, 87, 84, 89, 84, 91,
-84, 96, 59, 78, 68, 91, 84, 105, 50, 70, 61, 72, 84, 110, 60, 58,
-84, 115, 70, 96, 75, 91, 84, 123, 67, 37, 69, 91, 85, 34, 85, 43,
-76, 47, 85, 38, 85, 39, 62, 42, 59, 80, 64, 43, 49, 56, 48, 40,
-48, 82, 85, 48, 85, 49, 74, 90, 85, 55, 85, 52, 58, 39, 73, 88,
-76, 59, 71, 94, 85, 60, 60, 59, 85, 69, 67, 100, 85, 70, 52, 114,
-85, 74, 62, 110, 68, 92, 85, 78, 85, 82, 59, 82, 85, 85, 56, 73,
-85, 89, 85, 94, 66, 112, 57, 40, 67, 104, 64, 107, 53, 92, 85, 98,
-60, 100, 73, 89, 52, 50, 85, 108, 85, 110, 59, 123, 60, 77, 70, 51,
-62, 48, 76, 96, 61, 34, 63, 44, 53, 111, 86, 34, 66, 48, 86, 36,
-86, 39, 86, 41, 50, 44, 86, 45, 86, 47, 86, 50, 86, 53, 50, 101,
-69, 103, 63, 114, 86, 66, 86, 65, 74, 120, 86, 75, 86, 63, 63, 115,
-86, 77, 86, 81, 86, 58, 86, 83, 86, 84, 86, 88, 86, 90, 86, 92,
-64, 110, 57, 42, 56, 74, 52, 44, 72, 65, 86, 102, 86, 103, 63, 99,
-66, 83, 75, 57, 86, 115, 86, 111, 86, 112, 52, 51, 77, 68, 72, 95,
-68, 108, 86, 121, 56, 75, 48, 67, 86, 122, 86, 126, 87, 36, 87, 40,
-87, 44, 87, 48, 87, 50, 53, 93, 68, 111, 87, 56, 68, 37, 87, 59,
-87, 61, 87, 65, 87, 68, 68, 38, 87, 71, 64, 44, 78, 39, 70, 64,
-56, 102, 87, 84, 69, 48, 63, 52, 71, 38, 59, 86, 87, 88, 88, 45,
-87, 87, 87, 99, 87, 96, 53, 94, 54, 49, 87, 106, 87, 113, 54, 50,
-87, 107, 87, 117, 66, 41, 87, 122, 88, 39, 88, 35, 77, 42, 48, 45,
-88, 44, 62, 112, 79, 71, 64, 75, 87, 124, 88, 61, 88, 60, 88, 52,
-88, 51, 52, 54, 88, 71, 88, 70, 88, 64, 88, 88, 88, 87, 55, 69,
-88, 85, 77, 93, 88, 96, 88, 94, 74, 48, 88, 99, 88, 107, 88, 106,
-50, 123, 88, 112, 68, 40, 88, 118, 88, 121, 50, 124, 108, 67, 89, 35,
-66, 87, 75, 60, 72, 98, 66, 71, 89, 42, 89, 46, 73, 94, 53, 59,
-71, 68, 89, 56, 66, 114, 72, 100, 68, 113, 89, 68, 89, 66, 89, 57,
-51, 72, 51, 103, 59, 34, 59, 125, 89, 72, 53, 115, 89, 75, 68, 114,
-66, 42, 74, 97, 74, 123, 55, 126, 89, 87, 62, 56, 89, 85, 78, 43,
-65, 60, 68, 79, 89, 97, 89, 102, 77, 44, 48, 46, 52, 120, 77, 73,
-89, 108, 89, 109, 89, 110, 89, 107, 58, 113, 89, 119, 69, 38, 89, 116,
-89, 118, 55, 98, 59, 53, 70, 53, 89, 124, 51, 73, 90, 35, 90, 34,
-90, 43, 53, 60, 90, 49, 90, 53, 90, 55, 90, 59, 59, 89, 50, 126,
-56, 78, 73, 82, 54, 53, 59, 54, 63, 116, 90, 76, 73, 76, 69, 77,
-48, 54, 90, 81, 90, 82, 90, 85, 64, 123, 52, 122, 90, 92, 61, 92,
-50, 34, 58, 43, 48, 87, 64, 49, 62, 60, 67, 107, 90, 105, 90, 108,
-90, 110, 64, 50, 54, 71, 90, 117, 90, 120, 68, 42, 74, 107, 91, 34,
-91, 33, 91, 35, 91, 37, 91, 41, 82, 88, 55, 110, 58, 115, 91, 46,
-76, 90, 75, 81, 91, 51, 63, 121, 60, 93, 91, 57, 91, 66, 53, 79,
-72, 68, 91, 62, 75, 109, 79, 72, 56, 79, 91, 84, 74, 65, 91, 85,
-68, 83, 91, 82, 91, 75, 58, 58, 64, 114, 91, 89, 91, 91, 64, 115,
-91, 92, 91, 93, 91, 98, 91, 99, 91, 111, 91, 117, 91, 116, 57, 60,
-62, 63, 91, 104, 91, 110, 52, 126, 75, 64, 69, 111, 63, 57, 92, 42,
-92, 38, 68, 71, 63, 122, 92, 48, 92, 63, 92, 61, 77, 76, 92, 56,
-92, 65, 92, 68, 92, 60, 92, 57, 58, 103, 79, 49, 92, 85, 92, 70,
-92, 80, 116, 34, 92, 74, 92, 79, 92, 97, 92, 96, 65, 101, 92, 104,
-92, 102, 92, 100, 56, 34, 62, 65, 92, 109, 53, 76, 92, 115, 92, 111,
-51, 96, 92, 122, 93, 33, 92, 125, 93, 40, 93, 38, 93, 37, 93, 42,
-54, 123, 72, 39, 93, 50, 77, 115, 93, 51, 49, 53, 50, 36, 77, 95,
-54, 86, 93, 60, 52, 63, 93, 67, 74, 98, 58, 80, 93, 71, 61, 94,
-93, 77, 93, 79, 93, 82, 59, 38, 53, 35, 70, 71, 93, 91, 93, 93,
-93, 97, 93, 98, 93, 102, 63, 101, 72, 69, 72, 70, 49, 120, 93, 113,
-53, 98, 53, 37, 68, 64, 93, 115, 75, 87, 75, 119, 74, 40, 93, 117,
-93, 119, 93, 123, 67, 109, 49, 75, 77, 78, 64, 118, 68, 69, 61, 39,
-94, 42, 94, 54, 94, 49, 73, 98, 63, 59, 94, 58, 94, 50, 51, 54,
-78, 67, 94, 66, 61, 74, 94, 68, 94, 70, 61, 95, 64, 54, 55, 76,
-94, 97, 50, 57, 94, 98, 94, 92, 94, 90, 62, 69, 77, 47, 94, 83,
-79, 81, 72, 46, 61, 96, 48, 110, 94, 106, 69, 46, 94, 107, 51, 106,
-66, 108, 94, 118, 95, 35, 53, 121, 79, 51, 71, 121, 76, 33, 65, 50,
-52, 67, 55, 105, 51, 99, 95, 44, 95, 38, 95, 45, 95, 48, 95, 54,
-69, 67, 55, 99, 95, 62, 95, 59, 77, 116, 111, 105, 95, 71, 95, 68,
-73, 78, 95, 79, 64, 37, 95, 81, 94, 117, 70, 103, 95, 84, 69, 116,
-60, 94, 79, 39, 95, 85, 95, 89, 95, 90, 78, 117, 95, 96, 95, 88,
-95, 98, 95, 97, 49, 107, 76, 53, 65, 51, 78, 123, 95, 102, 95, 105,
-95, 108, 64, 122, 95, 103, 77, 80, 61, 79, 95, 114, 95, 116, 71, 51,
-95, 121, 83, 91, 95, 123, 96, 33, 71, 122, 96, 36, 96, 37, 96, 38,
-96, 42, 96, 44, 96, 47, 68, 45, 76, 70, 75, 82, 64, 55, 56, 35,
-96, 54, 96, 55, 53, 62, 56, 36, 62, 117, 54, 56, 96, 64, 65, 64,
-60, 109, 96, 70, 96, 73, 96, 75, 96, 80, 96, 78, 96, 81, 96, 82,
-61, 67, 96, 88, 96, 92, 56, 60, 54, 106, 52, 97, 96, 94, 96, 97,
-59, 57, 96, 100, 55, 62, 96, 105, 53, 101, 66, 118, 96, 106, 96, 109,
-96, 108, 96, 110, 96, 114, 58, 60, 96, 119, 96, 120, 96, 121, 52, 68,
-60, 37, 96, 123, 96, 125, 97, 33, 97, 37, 97, 41, 97, 44, 97, 48,
-52, 69, 59, 58, 69, 68, 68, 46, 97, 55, 48, 90, 78, 49, 97, 63,
-48, 91, 53, 38, 97, 73, 97, 75, 97, 79, 97, 87, 97, 86, 62, 73,
-97, 90, 97, 93, 65, 105, 97, 101, 97, 94, 97, 104, 97, 105, 97, 112,
-97, 113, 97, 116, 76, 126, 97, 117, 97, 124, 98, 33, 98, 36, 51, 39,
-59, 41, 98, 45, 72, 105, 98, 48, 98, 51, 98, 52, 69, 112, 98, 56,
-76, 92, 65, 106, 98, 64, 98, 70, 98, 68, 98, 71, 98, 73, 98, 74,
-98, 78, 98, 81, 98, 83, 98, 86, 61, 86, 98, 88, 98, 94, 98, 96,
-76, 112, 67, 59, 98, 101, 98, 102, 98, 105, 75, 36, 57, 92, 62, 75,
-78, 50, 98, 111, 98, 110, 72, 106, 98, 114, 98, 117, 51, 78, 98, 124,
-72, 88, 99, 34, 99, 33, 99, 36, 62, 76, 65, 67, 99, 40, 98, 104,
-60, 40, 53, 64, 99, 49, 61, 75, 73, 60, 69, 120, 54, 88, 50, 82,
-99, 53, 99, 54, 99, 58, 54, 89, 99, 61, 99, 62, 65, 69, 67, 97,
-48, 92, 99, 67, 76, 45, 99, 72, 60, 111, 99, 75, 75, 84, 48, 44,
-99, 81, 51, 79, 53, 102, 70, 77, 67, 98, 55, 34, 99, 93, 99, 96,
-51, 118, 99, 103, 99, 107, 61, 87, 99, 113, 81, 63, 99, 115, 99, 116,
-99, 121, 63, 90, 99, 119, 100, 38, 72, 53, 100, 56, 100, 42, 100, 44,
-74, 79, 100, 54, 100, 51, 67, 61, 100, 62, 64, 97, 100, 58, 100, 64,
-100, 65, 100, 74, 100, 71, 100, 77, 100, 76, 52, 74, 100, 84, 100, 83,
-100, 87, 64, 82, 100, 92, 100, 94, 74, 70, 76, 98, 74, 52, 71, 116,
-48, 64, 100, 104, 100, 111, 100, 114, 100, 117, 100, 118, 78, 72, 100, 122,
-53, 106, 101, 36, 61, 99, 65, 71, 59, 103, 101, 42, 101, 41, 101, 38,
-101, 45, 77, 109, 101, 49, 56, 40, 101, 53, 101, 52, 101, 70, 101, 64,
-101, 61, 76, 74, 54, 91, 101, 110, 68, 121, 76, 75, 101, 76, 101, 79,
-101, 83, 60, 74, 75, 37, 101, 92, 72, 75, 55, 82, 65, 54, 101, 90,
-55, 43, 101, 108, 101, 114, 101, 117, 101, 124, 52, 76, 102, 33, 102, 37,
-102, 42, 102, 45, 71, 77, 102, 48, 102, 53, 102, 57, 55, 50, 102, 62,
-102, 64, 102, 66, 61, 44, 63, 105, 52, 101, 102, 75, 57, 77, 66, 81,
-102, 83, 102, 85, 60, 42, 67, 63, 102, 88, 64, 59, 65, 111, 78, 126,
-102, 100, 102, 103, 102, 107, 52, 78, 56, 42, 58, 104, 48, 95, 66, 91,
-102, 114, 48, 125, 102, 120, 103, 38, 64, 72, 53, 83, 102, 123, 71, 62,
-103, 35, 102, 126, 79, 83, 103, 53, 60, 112, 68, 50, 103, 48, 57, 81,
-73, 102, 103, 51, 103, 56, 103, 63, 50, 50, 103, 66, 103, 71, 60, 43,
-67, 87, 103, 76, 54, 61, 80, 48, 61, 88, 103, 85, 103, 88, 103, 89,
-103, 91, 103, 96, 58, 49, 103, 103, 48, 114, 73, 103, 51, 41, 63, 68,
-54, 92, 52, 35, 49, 113, 50, 87, 60, 99, 49, 81, 103, 120, 51, 125,
-104, 35, 104, 52, 104, 42, 104, 39, 104, 41, 49, 65, 104, 58, 104, 46,
-103, 118, 52, 80, 104, 62, 104, 57, 104, 71, 54, 93, 62, 84, 104, 74,
-104, 65, 104, 72, 104, 68, 104, 76, 104, 78, 104, 84, 104, 98, 104, 94,
-67, 120, 73, 114, 104, 89, 48, 42, 104, 92, 61, 47, 73, 71, 104, 90,
-62, 120, 67, 95, 104, 108, 104, 107, 75, 41, 104, 122, 104, 81, 74, 78,
-104, 119, 104, 118, 74, 67, 104, 126, 105, 36, 104, 124, 105, 43, 105, 49,
-71, 118, 105, 51, 105, 45, 65, 38, 105, 55, 105, 52, 105, 57, 70, 35,
-61, 115, 105, 34, 105, 63, 105, 68, 77, 118, 105, 71, 105, 72, 53, 117,
-105, 76, 105, 77, 48, 58, 50, 99, 59, 61, 105, 79, 105, 85, 105, 86,
-51, 66, 51, 63, 72, 58, 72, 90, 66, 125, 75, 42, 105, 107, 67, 88,
-105, 114, 105, 110, 105, 111, 64, 102, 106, 33, 105, 118, 106, 35, 105, 122,
-71, 104, 77, 59, 106, 38, 106, 46, 77, 102, 106, 47, 106, 44, 106, 54,
-106, 52, 51, 42, 106, 36, 106, 55, 106, 66, 106, 67, 106, 71, 61, 48,
-106, 74, 62, 87, 73, 61, 106, 85, 106, 83, 55, 54, 106, 88, 106, 81,
-72, 111, 106, 84, 106, 95, 78, 34, 106, 101, 106, 107, 106, 108, 106, 105,
-74, 35, 75, 43, 106, 124, 106, 116, 106, 121, 106, 118, 106, 123, 50, 40,
-106, 125, 107, 36, 107, 38, 107, 40, 107, 42, 107, 44, 107, 46, 107, 49,
-107, 52, 51, 81, 107, 57, 63, 40, 107, 60, 56, 64, 63, 86, 107, 63,
-55, 109, 64, 95, 63, 71, 107, 73, 58, 62, 107, 71, 59, 110, 53, 77,
-107, 75, 56, 88, 107, 84, 56, 108, 107, 82, 50, 93, 53, 67, 67, 76,
-78, 74, 68, 53, 68, 124, 107, 97, 66, 122, 107, 104, 107, 108, 107, 111,
-107, 115, 54, 96, 107, 122, 107, 123, 55, 89, 53, 68, 108, 37, 90, 78,
-108, 43, 67, 43, 108, 47, 108, 50, 70, 90, 57, 107, 108, 56, 108, 58,
-75, 70, 108, 66, 57, 87, 64, 85, 108, 74, 50, 108, 66, 49, 108, 79,
-108, 77, 108, 81, 108, 83, 108, 87, 64, 86, 65, 118, 108, 99, 108, 100,
-60, 113, 66, 45, 108, 102, 108, 109, 108, 106, 64, 87, 108, 111, 65, 41,
-108, 117, 108, 116, 108, 118, 109, 41, 108, 125, 108, 122, 109, 35, 109, 38,
-109, 42, 109, 45, 109, 46, 109, 48, 109, 54, 109, 58, 63, 72, 109, 63,
-109, 65, 56, 46, 70, 112, 109, 71, 60, 52, 51, 83, 109, 76, 109, 79,
-109, 83, 109, 84, 109, 89, 109, 91, 109, 94, 55, 37, 63, 73, 82, 33,
-63, 43, 68, 84, 63, 87, 54, 97, 109, 107, 69, 51, 76, 66, 65, 119,
-109, 121, 109, 116, 66, 46, 66, 97, 48, 111, 63, 107, 74, 87, 110, 41,
-56, 47, 65, 120, 65, 43, 110, 50, 110, 54, 70, 97, 110, 56, 48, 106,
-79, 58, 110, 62, 73, 116, 77, 57, 110, 63, 110, 64, 69, 34, 70, 83,
-63, 108, 63, 93, 61, 55, 57, 115, 110, 78, 66, 105, 72, 48, 110, 79,
-110, 81, 110, 85, 72, 80, 110, 90, 110, 94, 75, 85, 110, 96, 110, 99,
-70, 95, 110, 98, 111, 79, 78, 107, 110, 111, 110, 107, 110, 105, 72, 45,
-57, 91, 75, 72, 65, 45, 110, 117, 65, 44, 110, 121, 110, 119, 61, 123,
-73, 70, 57, 93, 59, 44, 63, 109, 111, 35, 54, 83, 79, 63, 110, 125,
-68, 87, 111, 41, 55, 45, 111, 42, 51, 121, 58, 63, 51, 59, 111, 49,
-111, 55, 111, 57, 111, 56, 111, 52, 111, 63, 111, 65, 111, 60, 111, 67,
-111, 68, 111, 71, 52, 85, 111, 74, 111, 78, 111, 81, 111, 88, 68, 57,
-111, 89, 49, 60, 111, 95, 51, 85, 111, 99, 111, 102, 111, 106, 111, 107,
-70, 46, 111, 115, 73, 108, 111, 117, 75, 73, 48, 36, 111, 123, 74, 69,
-52, 89, 49, 34, 56, 49, 54, 121, 63, 111, 55, 100, 78, 89, 112, 46,
-64, 73, 50, 109, 59, 40, 63, 119, 49, 43, 49, 64, 60, 123, 78, 110,
-112, 67, 112, 69, 112, 71, 112, 73, 112, 77, 64, 68, 112, 80, 112, 83,
-112, 87, 112, 90, 112, 93, 112, 96, 112, 97, 112, 99, 112, 101, 112, 103,
-52, 90, 112, 108, 49, 36, 57, 96, 112, 114, 55, 91, 112, 117, 49, 80,
-112, 121, 52, 105, 78, 96, 112, 124, 73, 119, 113, 39, 113, 41, 72, 116,
-113, 43, 48, 59, 62, 126, 113, 46, 50, 110, 113, 51, 52, 91, 113, 57,
-113, 60, 113, 67, 60, 115, 113, 70, 67, 90, 71, 125, 67, 115, 113, 75,
-113, 79, 113, 84, 113, 87, 113, 86, 113, 89, 66, 77, 113, 91, 113, 93,
-113, 98, 113, 100, 113, 102, 57, 124, 51, 60, 63, 113, 113, 112, 113, 116,
-72, 49, 113, 124, 114, 34, 114, 35, 114, 38, 114, 45, 100, 120, 76, 37,
-114, 50, 53, 123, 79, 37, 114, 57, 48, 62, 114, 61, 75, 110, 114, 64,
-114, 65, 114, 66, 114, 75, 114, 76, 114, 80, 114, 90, 79, 76, 114, 92,
-114, 93, 48, 115, 51, 111, 114, 99, 75, 112, 114, 102, 114, 104, 68, 59,
-114, 108, 114, 112, 50, 42, 49, 117, 114, 115, 57, 99, 114, 125, 115, 37,
-49, 45, 75, 50, 115, 44, 115, 41, 115, 45, 115, 46, 114, 116, 115, 53,
-115, 49, 115, 55, 115, 57, 115, 60, 79, 73, 115, 63, 115, 64, 115, 67,
-60, 47, 115, 72, 115, 75, 78, 91, 115, 79, 115, 80, 50, 43, 115, 85,
-96, 84, 115, 93, 115, 95, 115, 99, 115, 103, 56, 93, 65, 77, 115, 108,
-73, 33, 115, 110, 115, 112, 115, 114, 115, 120, 115, 123, 78, 54, 115, 125,
-33, 42, 33, 92, 35, 53, 33, 41, 35, 73, 35, 83, 33, 79, 35, 103,
-35, 113, 33, 80, 27, 40, 73, 37, 47, 57, 67, 77, 87, 27, 36, 66,
-33, 49
-            });
-
-        super.setUp();
-    }
-
-    @Override
-    public void test_CodecDynamic() throws CharacterCodingException {
-        super.test_CodecDynamic();
-    }
-
-    @Override
-    public void test_Decode() throws CharacterCodingException {
-        super.test_Decode();
-    }
-
-    @Override
-    public void test_Encode() throws CharacterCodingException {
-        super.test_Encode();
-    }
-
+  @Override protected void setUp() throws Exception {
+    charsetName = "ISO-2022-JP";
+    testChars = "東京 とうきょう トウキョウ Tokyo 123".toCharArray();
+    testBytes = theseBytes(0x1b, 0x24, 0x42, 0x45, 0x6c, 0x35, 0x7e, 0x1b,
+                           0x28, 0x42, 0x20, 0x1b, 0x24, 0x42, 0x24, 0x48,
+                           0x24, 0x26, 0x24, 0x2d, 0x24, 0x67, 0x24, 0x26,
+                           0x1b, 0x28, 0x42, 0x20, 0x1b, 0x24, 0x42, 0x25,
+                           0x48, 0x25, 0x26, 0x25, 0x2d, 0x25, 0x67, 0x25,
+                           0x26, 0x1b, 0x28, 0x42, 0x20, 0x54, 0x6f, 0x6b,
+                           0x79, 0x6f, 0x20, 0x31, 0x32, 0x33);
+    super.setUp();
+  }
 }
diff --git a/luni/src/test/java/libcore/java/security/SecureRandomTest.java b/luni/src/test/java/libcore/java/security/SecureRandomTest.java
index 8199120..f9edbaa 100644
--- a/luni/src/test/java/libcore/java/security/SecureRandomTest.java
+++ b/luni/src/test/java/libcore/java/security/SecureRandomTest.java
@@ -16,8 +16,6 @@
 
 package libcore.java.security;
 
-import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider;
-
 import java.security.Provider;
 import java.security.SecureRandom;
 import java.security.Security;
@@ -27,7 +25,7 @@
 import junit.framework.TestCase;
 
 public class SecureRandomTest extends TestCase {
-    private static final Class<? extends Provider> EXPECTED_PROVIDER = OpenSSLProvider.class;
+    private static final String EXPECTED_PROVIDER = "com.android.org.conscrypt.OpenSSLProvider";
 
     private static final byte[] STATIC_SEED_BYTES = new byte[] {
             0x0A, (byte) 0xA0, 0x01, 0x10, (byte) 0xFF, (byte) 0xF0, 0x0F
@@ -99,16 +97,16 @@
     public void testGetCommonInstances_Success() throws Exception {
         SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
         assertNotNull(sr);
-        assertEquals(EXPECTED_PROVIDER, sr.getProvider().getClass());
+        assertEquals(EXPECTED_PROVIDER, sr.getProvider().getClass().getName());
     }
 
     public void testNewConstructors_Success() throws Exception {
         SecureRandom sr1 = new SecureRandom();
-        assertEquals(EXPECTED_PROVIDER, sr1.getProvider().getClass());
+        assertEquals(EXPECTED_PROVIDER, sr1.getProvider().getClass().getName());
         test_SecureRandom(sr1);
 
         SecureRandom sr2 = new SecureRandom(STATIC_SEED_BYTES);
-        assertEquals(EXPECTED_PROVIDER, sr2.getProvider().getClass());
+        assertEquals(EXPECTED_PROVIDER, sr2.getProvider().getClass().getName());
         test_SecureRandom(sr2);
     }
 }
diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java
index 4afc67d..7f8b4f4 100644
--- a/luni/src/test/java/libcore/java/security/SignatureTest.java
+++ b/luni/src/test/java/libcore/java/security/SignatureTest.java
@@ -16,10 +16,6 @@
 
 package libcore.java.security;
 
-import org.apache.harmony.xnet.provider.jsse.NativeCryptoTest;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider;
-
 import java.math.BigInteger;
 import java.security.InvalidKeyException;
 import java.security.KeyFactory;
@@ -31,7 +27,6 @@
 import java.security.Security;
 import java.security.Signature;
 import java.security.SignatureException;
-import java.security.interfaces.RSAPrivateKey;
 import java.security.spec.DSAPrivateKeySpec;
 import java.security.spec.DSAPublicKeySpec;
 import java.security.spec.InvalidKeySpecException;
@@ -86,78 +81,6 @@
         }
     }
 
-    public void test_getInstance_OpenSSL_ENGINE() throws Exception {
-        final String pem_private = "-----BEGIN RSA PRIVATE KEY-----\n"
-                + "MIICXAIBAAKBgQDpm4KamxulJnycEzNONGM7p0CvAaoZxJEd5Dvio5b6BROdCtRN\n"
-                + "lEsB+9vtB5thkyDVC7N+IW0AjtyDE6h2QP+AWa+c4dh0RM2uNVXkUWPrA8C++GHv\n"
-                + "EDlxZzRGiQEMuippYfIyBVkO+4+GRvnkG4dKjzxrQYPqKUK3C4PgFW2FewIDAQAB\n"
-                + "AoGAGUTSBsk6X03fcr588TundD9uNr/2V1002Ufj1msdnKPJ8FXIiy+8QVWt/2Cw\n"
-                + "RQi2J3VhkAYrlUDex2rr8Qas3E9uuwKgg/MZ4EsJbnKKgkd7uBZfmZ2ogcNJ82u7\n"
-                + "teVijFpdsVLDa9aczEppt5sZzyTaBrovrRb+AIRDpMw3I0ECQQD3JkWeQUA9Is1V\n"
-                + "z0X/ly/kaQKQLlrwYNdiKF0qOpyTLAguI7asAS72Zj7fThk5bHLM+mmgYwkicIIb\n"
-                + "67J32GQbAkEA8fkXqEnwMFYSkRmT9M/qUkwWUsMW12/AoZFI5gwKNDHZYxytGGLw\n"
-                + "mC//0qKnyeUG00vz06vLApe4/Sq4ODe6IQJBALEGastF9ZtUuDsEciD2y8kRJlLb\n"
-                + "wSt4Ug3u13yN6uTHnzxdPFTLrDW1WsdcC1lEQp5rpwjIpxxR9f/FvVl2V40CQHOY\n"
-                + "F6EhkUjGFaCTo4b0PHCMQK3Q3PyWOmP0z+p2HfnJRpx+eoKH4YASjhfF9HoSmywd\n"
-                + "wKGCFD1s1ca7vb29gYECQH86GmYZsDoLNWurEVJbkmCr7X1+xwim6umdrNKR27P7\n"
-                + "F1y0Sa3YY+LiiRb+IRSWE/onlP+28LIzWGF4lcTfDMc=\n"
-                + "-----END RSA PRIVATE KEY-----";
-
-        final byte[] der_public = new byte[] {
-                (byte) 0x30, (byte) 0x81, (byte) 0x9F, (byte) 0x30, (byte) 0x0D, (byte) 0x06,
-                (byte) 0x09, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xF7,
-                (byte) 0x0D, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00,
-                (byte) 0x03, (byte) 0x81, (byte) 0x8D, (byte) 0x00, (byte) 0x30, (byte) 0x81,
-                (byte) 0x89, (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xE9,
-                (byte) 0x9B, (byte) 0x82, (byte) 0x9A, (byte) 0x9B, (byte) 0x1B, (byte) 0xA5,
-                (byte) 0x26, (byte) 0x7C, (byte) 0x9C, (byte) 0x13, (byte) 0x33, (byte) 0x4E,
-                (byte) 0x34, (byte) 0x63, (byte) 0x3B, (byte) 0xA7, (byte) 0x40, (byte) 0xAF,
-                (byte) 0x01, (byte) 0xAA, (byte) 0x19, (byte) 0xC4, (byte) 0x91, (byte) 0x1D,
-                (byte) 0xE4, (byte) 0x3B, (byte) 0xE2, (byte) 0xA3, (byte) 0x96, (byte) 0xFA,
-                (byte) 0x05, (byte) 0x13, (byte) 0x9D, (byte) 0x0A, (byte) 0xD4, (byte) 0x4D,
-                (byte) 0x94, (byte) 0x4B, (byte) 0x01, (byte) 0xFB, (byte) 0xDB, (byte) 0xED,
-                (byte) 0x07, (byte) 0x9B, (byte) 0x61, (byte) 0x93, (byte) 0x20, (byte) 0xD5,
-                (byte) 0x0B, (byte) 0xB3, (byte) 0x7E, (byte) 0x21, (byte) 0x6D, (byte) 0x00,
-                (byte) 0x8E, (byte) 0xDC, (byte) 0x83, (byte) 0x13, (byte) 0xA8, (byte) 0x76,
-                (byte) 0x40, (byte) 0xFF, (byte) 0x80, (byte) 0x59, (byte) 0xAF, (byte) 0x9C,
-                (byte) 0xE1, (byte) 0xD8, (byte) 0x74, (byte) 0x44, (byte) 0xCD, (byte) 0xAE,
-                (byte) 0x35, (byte) 0x55, (byte) 0xE4, (byte) 0x51, (byte) 0x63, (byte) 0xEB,
-                (byte) 0x03, (byte) 0xC0, (byte) 0xBE, (byte) 0xF8, (byte) 0x61, (byte) 0xEF,
-                (byte) 0x10, (byte) 0x39, (byte) 0x71, (byte) 0x67, (byte) 0x34, (byte) 0x46,
-                (byte) 0x89, (byte) 0x01, (byte) 0x0C, (byte) 0xBA, (byte) 0x2A, (byte) 0x69,
-                (byte) 0x61, (byte) 0xF2, (byte) 0x32, (byte) 0x05, (byte) 0x59, (byte) 0x0E,
-                (byte) 0xFB, (byte) 0x8F, (byte) 0x86, (byte) 0x46, (byte) 0xF9, (byte) 0xE4,
-                (byte) 0x1B, (byte) 0x87, (byte) 0x4A, (byte) 0x8F, (byte) 0x3C, (byte) 0x6B,
-                (byte) 0x41, (byte) 0x83, (byte) 0xEA, (byte) 0x29, (byte) 0x42, (byte) 0xB7,
-                (byte) 0x0B, (byte) 0x83, (byte) 0xE0, (byte) 0x15, (byte) 0x6D, (byte) 0x85,
-                (byte) 0x7B, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01
-        };
-
-        // We only need to test this on the OpenSSL provider.
-        Provider p = Security.getProvider(OpenSSLProvider.PROVIDER_NAME);
-
-        /* ENGINE-based private key */
-        NativeCryptoTest.loadTestEngine();
-        OpenSSLEngine engine = OpenSSLEngine.getInstance(NativeCryptoTest.TEST_ENGINE_ID);
-        PrivateKey privKey = engine.getPrivateKeyById(pem_private);
-        assertTrue(privKey instanceof RSAPrivateKey);
-
-        /* Non-ENGINE-based public key */
-        KeyFactory kf = KeyFactory.getInstance("RSA", p);
-        PublicKey pubKey = kf.generatePublic(new X509EncodedKeySpec(der_public));
-
-        KeyPair kp = new KeyPair(pubKey, privKey);
-
-        Set<Provider.Service> services = p.getServices();
-        for (Provider.Service service : services) {
-            if ("Signature".equals(service.getType()) && service.getAlgorithm().contains("RSA")) {
-                Signature sig1 = Signature.getInstance(service.getAlgorithm(), p);
-                test_Signature(sig1, kp);
-            }
-        }
-
-    }
-
     private final Map<String, KeyPair> keypairAlgorithmToInstance
             = new HashMap<String, KeyPair>();
 
diff --git a/luni/src/test/java/libcore/java/text/CollatorTest.java b/luni/src/test/java/libcore/java/text/CollatorTest.java
index 0c718c8..0a61f04 100644
--- a/luni/src/test/java/libcore/java/text/CollatorTest.java
+++ b/luni/src/test/java/libcore/java/text/CollatorTest.java
@@ -134,15 +134,19 @@
         assertCollationElementIterator(coll.getCollationElementIterator(it), offsets);
     }
 
-    public void testGetCollationElementIteratorString() throws Exception {
-        assertGetCollationElementIteratorString(new Locale("es", "", "TRADITIONAL"), "cha", 0, 2, 3);
+    public void testGetCollationElementIteratorString_es() throws Exception {
         assertGetCollationElementIteratorString(new Locale("es", "", ""), "cha", 0, 1, 2, 3);
+    }
+
+    public void testGetCollationElementIteratorString_de_DE() throws Exception {
         assertGetCollationElementIteratorString(new Locale("de", "DE", ""), "\u00e6b", 0, 1, 1, 1, 1, 2);
     }
 
-    public void testGetCollationElementIteratorCharacterIterator() throws Exception {
-        assertGetCollationElementIteratorCharacterIterator(new Locale("es", "", "TRADITIONAL"), "cha", 0, 2, 3);
+    public void testGetCollationElementIteratorCharacterIterator_es() throws Exception {
         assertGetCollationElementIteratorCharacterIterator(new Locale("es", "", ""), "cha", 0, 1, 2, 3);
+    }
+
+    public void testGetCollationElementIteratorCharacterIterator_de_DE() throws Exception {
         assertGetCollationElementIteratorCharacterIterator(new Locale("de", "DE", ""), "\u00e6b", 0, 1, 1, 1, 1, 2);
     }
 }
diff --git a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
index a2f93a8..1e40f8a 100644
--- a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
@@ -22,8 +22,8 @@
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.text.NumberFormat;
+import java.util.Currency;
 import java.util.Locale;
-import tests.support.Support_Locale;
 
 public class DecimalFormatTest extends junit.framework.TestCase {
     public void test_exponentSeparator() throws Exception {
@@ -80,11 +80,9 @@
         assertDecFmtWithMultiplierAndFractionByLocale("3330000000000000000000000000000000", 3, 4,
                     Locale.US, "9,990,000,000,000,000,000,000,000,000,000,000");
 
-        Locale inLocale = new Locale("en", "IN");
-        if (Support_Locale.isLocaleAvailable(inLocale)) {
-            assertDecFmtWithMultiplierAndFractionByLocale("3330000000000000000000000000000000", 3, 4,
-                    inLocale, "9,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,000");
-        }
+        Locale en_IN = new Locale("en", "IN");
+        assertDecFmtWithMultiplierAndFractionByLocale("3330000000000000000000000000000000", 3, 4,
+                en_IN, "9,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,000");
     }
 
     public void testBigDecimalTestBigIntWithMultiplier() {
@@ -103,22 +101,20 @@
         assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", -10, 0,
                 Locale.US, "-987,654,321,098,765,432,109,876,543,210");
 
-        Locale inLocale = new Locale("en", "IN");
-        if (Support_Locale.isLocaleAvailable(inLocale)) {
-            assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", 10, 0,
-                    inLocale, "1,23,45,67,89,01,23,450");
-            assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", 10, 0,
-                    inLocale, "12,34,56,78,90,12,34,56,78,900");
-            assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", 10, 0,
-                    inLocale, "9,87,65,43,21,09,87,65,43,21,09,87,65,43,210");
+        Locale en_IN = new Locale("en", "IN");
+        assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", 10, 0,
+                en_IN, "1,23,45,67,89,01,23,450");
+        assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", 10, 0,
+                en_IN, "12,34,56,78,90,12,34,56,78,900");
+        assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", 10, 0,
+                en_IN, "9,87,65,43,21,09,87,65,43,21,09,87,65,43,210");
 
-            assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", -10, 0,
-                    inLocale, "-1,23,45,67,89,01,23,450");
-            assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", -10, 0,
-                    inLocale, "-12,34,56,78,90,12,34,56,78,900");
-            assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", -10, 0,
-                    inLocale, "-9,87,65,43,21,09,87,65,43,21,09,87,65,43,210");
-        }
+        assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", -10, 0,
+                en_IN, "-1,23,45,67,89,01,23,450");
+        assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", -10, 0,
+                en_IN, "-12,34,56,78,90,12,34,56,78,900");
+        assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", -10, 0,
+                en_IN, "-9,87,65,43,21,09,87,65,43,21,09,87,65,43,210");
     }
 
     public void testBigDecimalICUConsistency() {
@@ -176,4 +172,29 @@
         BigDecimal d = new BigDecimal(value);
         assertEquals(expectedResult, df.format(d));
     }
+
+    public void testSetZeroDigitForPattern() {
+        DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
+        decimalFormatSymbols.setZeroDigit('a');
+        DecimalFormat formatter = new DecimalFormat();
+        formatter.setDecimalFormatSymbols(decimalFormatSymbols);
+        formatter.applyLocalizedPattern("#.aa");
+        assertEquals("e.fa", formatter.format(4.50));
+    }
+
+    public void testSetZeroDigitForFormatting() {
+        DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
+        decimalFormatSymbols.setZeroDigit('a');
+        DecimalFormat formatter = new DecimalFormat();
+        formatter.setDecimalFormatSymbols(decimalFormatSymbols);
+        formatter.applyLocalizedPattern("#");
+        assertEquals("eadacab", formatter.format(4030201));
+    }
+
+    public void testBug9087737() throws Exception {
+        DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.US);
+        // These shouldn't make valgrind unhappy.
+        df.setCurrency(Currency.getInstance("CHF"));
+        df.setCurrency(Currency.getInstance("GBP"));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/text/NumberFormatTest.java b/luni/src/test/java/libcore/java/text/NumberFormatTest.java
index ce80bd1..1a14462 100644
--- a/luni/src/test/java/libcore/java/text/NumberFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/NumberFormatTest.java
@@ -23,7 +23,6 @@
 import java.text.NumberFormat;
 import java.text.ParsePosition;
 import java.util.Locale;
-import tests.support.Support_Locale;
 
 public class NumberFormatTest extends junit.framework.TestCase {
     // NumberFormat.format(Object, StringBuffer, FieldPosition) guarantees it calls doubleValue for
@@ -66,9 +65,6 @@
     }
 
     public void test_getIntegerInstance_ar() throws Exception {
-        if (!Support_Locale.isLocaleAvailable(new Locale("ar"))) {
-            return;
-        }
         NumberFormat numberFormat = NumberFormat.getNumberInstance(new Locale("ar"));
         assertEquals("#0.###;#0.###-", ((DecimalFormat) numberFormat).toPattern());
         NumberFormat integerFormat = NumberFormat.getIntegerInstance(new Locale("ar"));
@@ -77,9 +73,6 @@
 
     public void test_numberLocalization() throws Exception {
         Locale arabic = new Locale("ar");
-        if (!Support_Locale.isLocaleAvailable(arabic)) {
-            return;
-        }
         NumberFormat nf = NumberFormat.getNumberInstance(arabic);
         assertEquals('\u0660', new DecimalFormatSymbols(arabic).getZeroDigit());
         assertEquals("١٢٣٤٥٦٧٨٩٠", nf.format(1234567890));
diff --git a/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java b/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java
index 7bb5545..b7ae098 100644
--- a/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java
@@ -26,7 +26,6 @@
 import java.util.Currency;
 import java.util.Locale;
 import junit.framework.TestCase;
-import tests.support.Support_Locale;
 
 public class OldNumberFormatTest extends TestCase {
 
@@ -41,25 +40,22 @@
 
         // try with a locale that has a different integer pattern
         Locale chLocale = new Locale("de", "CH");
-        if (Support_Locale.isLocaleAvailable(chLocale)) {
-            format = (DecimalFormat) NumberFormat.getIntegerInstance(chLocale);
-            assertEquals("#,##0", format.toPattern());
-            assertEquals("-36", format.format(-35.76));
-            assertEquals(new Long(-36), format.parse("-36"));
-            assertEquals(new Long(-36), format.parseObject("-36"));
-            assertEquals(0, format.getMaximumFractionDigits());
-            assertTrue(format.isParseIntegerOnly());
-        }
+        format = (DecimalFormat) NumberFormat.getIntegerInstance(chLocale);
+        assertEquals("#,##0", format.toPattern());
+        assertEquals("-36", format.format(-35.76));
+        assertEquals(new Long(-36), format.parse("-36"));
+        assertEquals(new Long(-36), format.parseObject("-36"));
+        assertEquals(0, format.getMaximumFractionDigits());
+        assertTrue(format.isParseIntegerOnly());
+
         Locale arLocale = new Locale("ar", "AE");
-        if (Support_Locale.isLocaleAvailable(arLocale)) {
-            format = (DecimalFormat) NumberFormat.getIntegerInstance(arLocale);
-            assertEquals("#0;#0-", format.toPattern());
-            assertEquals("\u0666-", format.format(-6));
-            assertEquals(new Long(-36), format.parse("36-"));
-            assertEquals(new Long(-36), format.parseObject("36-"));
-            assertEquals(0, format.getMaximumFractionDigits());
-            assertTrue(format.isParseIntegerOnly());
-        }
+        format = (DecimalFormat) NumberFormat.getIntegerInstance(arLocale);
+        assertEquals("#0;#0-", format.toPattern());
+        assertEquals("\u0666-", format.format(-6));
+        assertEquals(new Long(-36), format.parse("36-"));
+        assertEquals(new Long(-36), format.parseObject("36-"));
+        assertEquals(0, format.getMaximumFractionDigits());
+        assertTrue(format.isParseIntegerOnly());
     }
 
     public void test_setMaximumIntegerDigits() {
@@ -114,15 +110,11 @@
         parseObjectTest(NumberFormat.getInstance(), "123.123abc123",
                 new ParsePosition(3), new Double(0.123), 7, true);
 
-        if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
-            parseObjectTest(NumberFormat.getInstance(Locale.FRANCE),
-                "asd123,123abc123",
-                new ParsePosition(3), new Double(123.123), 10, true);
+        parseObjectTest(NumberFormat.getInstance(Locale.FRANCE), "asd123,123abc123",
+                        new ParsePosition(3), new Double(123.123), 10, true);
 
-            parseObjectTest(NumberFormat.getInstance(Locale.FRANCE),
-                "test test",
-                new ParsePosition(0), null, 0, false);
-        }
+        parseObjectTest(NumberFormat.getInstance(Locale.FRANCE), "test test",
+                        new ParsePosition(0), null, 0, false);
 
         parseObjectTest(NumberFormat.getIntegerInstance(),
                 "asd123.123abc123",
@@ -222,14 +214,12 @@
                 out.toString());
 
         Locale deLocale = new Locale("de", "CH");
-        if (Support_Locale.isLocaleAvailable(deLocale)) {
-            NumberFormat nf2 = NumberFormat.getInstance(deLocale);
-            out = nf2.format(-1234567890.0123456789);
-            // use de_CH instead
-            // assertEquals("Wrong result for double : " + out, "1,234,567,890.012-",
-            //         out.toString());
-            assertEquals("Wrong result for double : " + out, "-1'234'567'890.012", out.toString());
-        }
+        NumberFormat nf2 = NumberFormat.getInstance(deLocale);
+        out = nf2.format(-1234567890.0123456789);
+        // use de_CH instead
+        // assertEquals("Wrong result for double : " + out, "1,234,567,890.012-",
+        //         out.toString());
+        assertEquals("Wrong result for double : " + out, "-1'234'567'890.012", out.toString());
 
         out = nf1.format(1.0001);
         assertEquals("Wrong result for for double: " + out, "1", out.toString());
@@ -251,14 +241,12 @@
                 "-9,223,372,036,854,775,808", out.toString());
 
         Locale deLocale = new Locale("de", "CH");
-        if (Support_Locale.isLocaleAvailable(deLocale)) {
-            NumberFormat nf2 = NumberFormat.getInstance(deLocale);
-            out = nf2.format(-1234567890);
-            // use de_CH instead
-            // assertEquals("Wrong result for double : " + out, "-1 234 567 890", out
-            //         .toString());
-            assertEquals("Wrong result for double : " + out, "-1'234'567'890", out.toString());
-        }
+        NumberFormat nf2 = NumberFormat.getInstance(deLocale);
+        out = nf2.format(-1234567890);
+        // use de_CH instead
+        // assertEquals("Wrong result for double : " + out, "-1 234 567 890", out
+        //         .toString());
+        assertEquals("Wrong result for double : " + out, "-1'234'567'890", out.toString());
 
         // the Locale data of icu uses \uc2a0
         out = nf1.format(1);
@@ -322,18 +310,16 @@
         assertEquals("$1.00", format.format(0.999));
 
         Locale atLocale = new Locale("de", "AT");
-        if (Support_Locale.isLocaleAvailable(atLocale)) {
-            format = NumberFormat.getCurrencyInstance(atLocale);
-            // BEGIN android-changed: ICU uses non-breaking space after the euro sign; the RI uses ' '.
-            assertEquals("\u20ac\u00a035,76", format.format(35.76));
-            assertEquals("\u20ac\u00a0123.456,79", format.format(123456.789));
-            assertEquals("\u20ac\u00a00,10", format.format(0.1));
-            assertEquals("\u20ac\u00a01,00", format.format(0.999));
-            try {
-                NumberFormat.getCurrencyInstance(null);
-                fail("java.lang.NullPointerException is not thrown");
-            } catch (java.lang.NullPointerException expected) {
-            }
+        format = NumberFormat.getCurrencyInstance(atLocale);
+        // BEGIN android-changed: ICU uses non-breaking space after the euro sign; the RI uses ' '.
+        assertEquals("\u20ac\u00a035,76", format.format(35.76));
+        assertEquals("\u20ac\u00a0123.456,79", format.format(123456.789));
+        assertEquals("\u20ac\u00a00,10", format.format(0.1));
+        assertEquals("\u20ac\u00a01,00", format.format(0.999));
+        try {
+            NumberFormat.getCurrencyInstance(null);
+            fail("java.lang.NullPointerException is not thrown");
+        } catch (java.lang.NullPointerException expected) {
         }
     }
 
@@ -357,18 +343,17 @@
     }
 
     public void test_getInstanceLjava_util_Locale() {
-        Locale testLocale = new Locale("de", "CH");
+        Locale de_CH = new Locale("de", "CH");
         Locale.setDefault(Locale.US);
-        if (Support_Locale.isLocaleAvailable(testLocale)) {
-            NumberFormat format = NumberFormat.getInstance(testLocale);
+        NumberFormat format = NumberFormat.getInstance(de_CH);
 
-            assertNotSame(null, format);
-            assertTrue(format instanceof NumberFormat);
+        assertNotSame(null, format);
+        assertTrue(format instanceof NumberFormat);
 
-            assertEquals("1'234'567'890.099", format.format(1234567890.0987654321));
-            assertEquals("#,##0.###", ((DecimalFormat) format).toPattern());
-            assertEquals("123'456'789", format.format(123456789));
-        }
+        assertEquals("1'234'567'890.099", format.format(1234567890.0987654321));
+        assertEquals("#,##0.###", ((DecimalFormat) format).toPattern());
+        assertEquals("123'456'789", format.format(123456789));
+
         try {
             NumberFormat.getInstance(null);
             fail("java.lang.NullPointerException is not thrown");
@@ -398,15 +383,14 @@
     public void test_getNumberInstanceLjava_util_Locale() {
         Locale.setDefault(Locale.US);
         Locale deLocale = new Locale("de", "CH");
-        if (Support_Locale.isLocaleAvailable(deLocale)) {
-            NumberFormat format = NumberFormat.getNumberInstance(deLocale);
-            assertNotSame("Instance is null", null, format);
-            assertTrue("Object is not instance of NumberFormat", format instanceof NumberFormat);
+        NumberFormat format = NumberFormat.getNumberInstance(deLocale);
+        assertNotSame("Instance is null", null, format);
+        assertTrue("Object is not instance of NumberFormat", format instanceof NumberFormat);
 
-            assertEquals("-1'234'567'890.099", format.format(-1234567890.0987654321));
-            assertEquals("#,##0.###", ((DecimalFormat) format).toPattern());
-            assertEquals("123'456'789", format.format(123456789));
-        }
+        assertEquals("-1'234'567'890.099", format.format(-1234567890.0987654321));
+        assertEquals("#,##0.###", ((DecimalFormat) format).toPattern());
+        assertEquals("123'456'789", format.format(123456789));
+
         try {
             NumberFormat.getInstance(null);
             fail("java.lang.NullPointerException is not thrown");
@@ -436,16 +420,15 @@
     public void test_getPercentInstanceLjava_util_Locale() {
         Locale csLocale = new Locale("cs", "CZ");
         Locale.setDefault(Locale.US);
-        if (Support_Locale.isLocaleAvailable(csLocale)) {
-            NumberFormat format = NumberFormat.getPercentInstance(csLocale);
 
-            assertNotSame("Instance is null", null, format);
-            assertTrue("Object is not instance of NumberFormat", format instanceof NumberFormat);
+        NumberFormat format = NumberFormat.getPercentInstance(csLocale);
+        assertNotSame("Instance is null", null, format);
+        assertTrue("Object is not instance of NumberFormat", format instanceof NumberFormat);
 
-            assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", format.format(1234567890.0987654321));
-            assertEquals("#,##0\u00a0%", ((DecimalFormat) format).toPattern());
-            assertEquals("12\u00a0345\u00a0678\u00a0900\u00a0%", format.format(123456789));
-        }
+        assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", format.format(1234567890.0987654321));
+        assertEquals("#,##0\u00a0%", ((DecimalFormat) format).toPattern());
+        assertEquals("12\u00a0345\u00a0678\u00a0900\u00a0%", format.format(123456789));
+
         try {
             NumberFormat.getInstance(null);
             fail("java.lang.NullPointerException is not thrown");
@@ -602,25 +585,23 @@
                 "-1,234,567,890.1", nf1.format(-1234567890.1));
 
         Locale csLocale = new Locale("cs", "CZ");
-        if (Support_Locale.isLocaleAvailable(csLocale)) {
-            NumberFormat nf2 = NumberFormat.getPercentInstance(csLocale);
-            nf2.setGroupingUsed(false);
+        NumberFormat nf2 = NumberFormat.getPercentInstance(csLocale);
+        nf2.setGroupingUsed(false);
 
-            assertEquals("123456789010\u00a0%", nf2.format(1234567890.1));
+        assertEquals("123456789010\u00a0%", nf2.format(1234567890.1));
 
-            assertEquals("-123456789010\u00a0%", nf2.format(-1234567890.1));
-            assertEquals("1,234,567,890.1", nf1.format(1234567890.1));
+        assertEquals("-123456789010\u00a0%", nf2.format(-1234567890.1));
+        assertEquals("1,234,567,890.1", nf1.format(1234567890.1));
 
-            nf2.setGroupingUsed(true);
-            assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(1234567890.1));
+        nf2.setGroupingUsed(true);
+        assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(1234567890.1));
 
-            assertEquals("-123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(-1234567890.1));
+        assertEquals("-123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(-1234567890.1));
 
-            nf2.setGroupingUsed(true);
-            assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(1234567890.1));
+        nf2.setGroupingUsed(true);
+        assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(1234567890.1));
 
-            assertEquals("-123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(-1234567890.1));
-        }
+        assertEquals("-123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(-1234567890.1));
     }
 
     public void test_isParseIntegerOnly() {
diff --git a/luni/src/test/java/libcore/java/util/FormatterTest.java b/luni/src/test/java/libcore/java/util/FormatterTest.java
index 596e946..043c06b 100644
--- a/luni/src/test/java/libcore/java/util/FormatterTest.java
+++ b/luni/src/test/java/libcore/java/util/FormatterTest.java
@@ -18,16 +18,14 @@
 
 import java.math.BigDecimal;
 import java.util.Calendar;
+import java.util.GregorianCalendar;
 import java.util.Locale;
 import java.util.TimeZone;
-import tests.support.Support_Locale;
 
 public class FormatterTest extends junit.framework.TestCase {
     public void test_numberLocalization() throws Exception {
         Locale arabic = new Locale("ar");
-        if (!Support_Locale.isLocaleAvailable(arabic)) {
-            return;
-        }
+
         // Check the fast path for %d:
         assertEquals("12 \u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\u0660 34",
                 String.format(arabic, "12 %d 34", 1234567890));
@@ -135,4 +133,42 @@
     public void test42936() throws Exception {
         assertEquals("0.00000000000000", String.format("%.15g",0.0d));
     }
+
+    // https://code.google.com/p/android/issues/detail?id=53983
+    public void test53983() throws Exception {
+      checkFormat("00", "H", 00);
+      checkFormat( "0", "k", 00);
+      checkFormat("12", "I", 00);
+      checkFormat("12", "l", 00);
+
+      checkFormat("01", "H", 01);
+      checkFormat( "1", "k", 01);
+      checkFormat("01", "I", 01);
+      checkFormat( "1", "l", 01);
+
+      checkFormat("12", "H", 12);
+      checkFormat("12", "k", 12);
+      checkFormat("12", "I", 12);
+      checkFormat("12", "l", 12);
+
+      checkFormat("13", "H", 13);
+      checkFormat("13", "k", 13);
+      checkFormat("01", "I", 13);
+      checkFormat( "1", "l", 13);
+
+      checkFormat("00", "H", 24);
+      checkFormat( "0", "k", 24);
+      checkFormat("12", "I", 24);
+      checkFormat("12", "l", 24);
+    }
+
+    private static void checkFormat(String expected, String pattern, int hour) {
+      TimeZone utc = TimeZone.getTimeZone("UTC");
+
+      Calendar c = new GregorianCalendar(utc);
+      c.set(2013, Calendar.JANUARY, 1, hour, 00);
+
+      assertEquals(expected, String.format(Locale.US, "%t" + pattern, c));
+      assertEquals(expected, String.format(Locale.US, "%T" + pattern, c));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/util/ObjectsTest.java b/luni/src/test/java/libcore/java/util/ObjectsTest.java
new file mode 100644
index 0000000..93be541
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/ObjectsTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+package libcore.java.util;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+public class ObjectsTest extends junit.framework.TestCase {
+  public static final class Hello {
+    public String toString() { return "hello"; }
+  }
+
+  public void test_compare() throws Exception {
+    assertEquals(0, Objects.compare(null, null, String.CASE_INSENSITIVE_ORDER));
+    assertEquals(0, Objects.compare("a", "A", String.CASE_INSENSITIVE_ORDER));
+    assertEquals(-1, Objects.compare("a", "b", String.CASE_INSENSITIVE_ORDER));
+    assertEquals(1, Objects.compare("b", "a", String.CASE_INSENSITIVE_ORDER));
+  }
+
+  public void test_deepEquals() throws Exception {
+    int[] xs = new int[3];
+    int[] ys = new int[4];
+    int[] zs = new int[3];
+    String[] o1 = new String[] { "hello" };
+    String[] o2 = new String[] { "world" };
+    String[] o3 = new String[] { "hello" };
+    assertTrue(Objects.deepEquals(null, null));
+    assertFalse(Objects.deepEquals(xs, null));
+    assertFalse(Objects.deepEquals(null, xs));
+    assertTrue(Objects.deepEquals(xs, xs));
+    assertTrue(Objects.deepEquals(xs, zs));
+    assertFalse(Objects.deepEquals(xs, ys));
+    assertTrue(Objects.deepEquals(o1, o1));
+    assertTrue(Objects.deepEquals(o1, o3));
+    assertFalse(Objects.deepEquals(o1, o2));
+    assertTrue(Objects.deepEquals("hello", "hello"));
+    assertFalse(Objects.deepEquals("hello", "world"));
+  }
+
+  public void test_equals() throws Exception {
+    Hello h1 = new Hello();
+    Hello h2 = new Hello();
+    assertTrue(Objects.equals(null, null));
+    assertFalse(Objects.equals(h1, null));
+    assertFalse(Objects.equals(null, h1));
+    assertFalse(Objects.equals(h1, h2));
+    assertTrue(Objects.equals(h1, h1));
+  }
+
+  public void test_hash() throws Exception {
+    assertEquals(Arrays.hashCode(new Object[0]), Objects.hash());
+    assertEquals(31, Objects.hash((Object) null));
+    assertEquals(0, Objects.hash((Object[]) null));
+    assertEquals(-1107615551, Objects.hash("hello", "world"));
+    assertEquals(23656287, Objects.hash("hello", "world", null));
+  }
+
+  public void test_hashCode() throws Exception {
+    Hello h = new Hello();
+    assertEquals(h.hashCode(), Objects.hashCode(h));
+    assertEquals(0, Objects.hashCode(null));
+  }
+
+  public void test_requireNonNull_T() throws Exception {
+    Hello h = new Hello();
+    assertEquals(h, Objects.requireNonNull(h));
+    try {
+      Objects.requireNonNull(null);
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals(null, expected.getMessage());
+    }
+  }
+
+  public void test_requireNonNull_T_String() throws Exception {
+    Hello h = new Hello();
+    assertEquals(h, Objects.requireNonNull(h, "test"));
+    try {
+      Objects.requireNonNull(null, "message");
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("message", expected.getMessage());
+    }
+    try {
+      Objects.requireNonNull(null, null);
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals(null, expected.getMessage());
+    }
+  }
+
+  public void test_toString_Object() throws Exception {
+    assertEquals("hello", Objects.toString(new Hello()));
+    assertEquals("null", Objects.toString(null));
+  }
+
+  public void test_toString_Object_String() throws Exception {
+    assertEquals("hello", Objects.toString(new Hello(), "world"));
+    assertEquals("world", Objects.toString(null, "world"));
+    assertEquals(null, Objects.toString(null, null));
+  }
+}
diff --git a/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java b/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java
index ad9009a..4bd858c 100644
--- a/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java
@@ -177,10 +177,8 @@
         assertFalse("Charset KLINGON must not be supported",
                 Charset.isSupported("KLINGON"));
 
-        // Make sure our local change to the real translation table used for
-        // EUC-JP doesn't get lost.
-        Charset cs = Charset.forName("EUC-JP");
-        assertTrue("EUC-JP must use 'ibm-954_P101-2007'", cs.aliases().contains("ibm-954_P101-2007"));
+        // Check we have the canonical EUC-JP charset.
+        assertEquals("EUC-JP", Charset.forName("EUC-JP").name());
     }
 
 }
diff --git a/luni/src/test/java/libcore/java/util/OldFormatterTest.java b/luni/src/test/java/libcore/java/util/OldFormatterTest.java
index 53d8eb2..3b4788b 100644
--- a/luni/src/test/java/libcore/java/util/OldFormatterTest.java
+++ b/luni/src/test/java/libcore/java/util/OldFormatterTest.java
@@ -24,7 +24,6 @@
 import java.util.IllegalFormatFlagsException;
 import java.util.Locale;
 import junit.framework.TestCase;
-import tests.support.Support_Locale;
 
 public final class OldFormatterTest extends TestCase {
 
@@ -59,21 +58,17 @@
         Formatter fNoL = null;
         cal.set(2008, Calendar.SEPTEMBER, 23, 18, 30);
 
-        if (Support_Locale.isLocaleAvailable(Locale.GERMAN)) {
-            fLoc = new Formatter(Locale.GERMAN);
-            fNoL = new Formatter(Locale.GERMAN);
-            fLoc.format(Locale.US, "%f", val);
-            fNoL.format("%f", val);
-            assertFalse(fLoc.toString().equals(fNoL.toString()));
-        }
+        fLoc = new Formatter(Locale.GERMAN);
+        fNoL = new Formatter(Locale.GERMAN);
+        fLoc.format(Locale.US, "%f", val);
+        fNoL.format("%f", val);
+        assertFalse(fLoc.toString().equals(fNoL.toString()));
 
-        if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
-            fLoc = new Formatter(Locale.FRANCE);
-            fNoL = new Formatter(Locale.FRANCE);
-            fLoc.format(Locale.US, "%f", val);
-            fNoL.format("%f", val);
-            assertFalse(fLoc.toString().equals(fNoL.toString()));
-        }
+        fLoc = new Formatter(Locale.FRANCE);
+        fNoL = new Formatter(Locale.FRANCE);
+        fLoc.format(Locale.US, "%f", val);
+        fNoL.format("%f", val);
+        assertFalse(fLoc.toString().equals(fNoL.toString()));
 
         fLoc = new Formatter(Locale.US);
         fNoL = new Formatter(Locale.US);
@@ -81,21 +76,17 @@
         fNoL.format("%f", val);
         assertTrue(fLoc.toString().equals(fNoL.toString()));
 
-        if (Support_Locale.isLocaleAvailable(Locale.GERMAN)) {
-            fLoc = new Formatter(Locale.GERMAN);
-            fNoL = new Formatter(Locale.GERMAN);
-            fLoc.format(Locale.US, "%tA %tB %td %tT", cal, cal,  cal, cal);
-            fNoL.format("%tA %tB %td %tT", cal, cal,  cal, cal);
-            assertFalse(fLoc.toString().equals(fNoL.toString()));
-        }
+        fLoc = new Formatter(Locale.GERMAN);
+        fNoL = new Formatter(Locale.GERMAN);
+        fLoc.format(Locale.US, "%tA %tB %td %tT", cal, cal,  cal, cal);
+        fNoL.format("%tA %tB %td %tT", cal, cal,  cal, cal);
+        assertFalse(fLoc.toString().equals(fNoL.toString()));
 
-        if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
-            fLoc = new Formatter(Locale.FRANCE);
-            fNoL = new Formatter(Locale.FRANCE);
-            fLoc.format(Locale.US, "%tA %tB %td %tT", cal, cal,  cal, cal);
-            fNoL.format("%tA %tB %td %tT", cal, cal,  cal, cal);
-            assertFalse(fLoc.toString().equals(fNoL.toString()));
-        }
+        fLoc = new Formatter(Locale.FRANCE);
+        fNoL = new Formatter(Locale.FRANCE);
+        fLoc.format(Locale.US, "%tA %tB %td %tT", cal, cal,  cal, cal);
+        fNoL.format("%tA %tB %td %tT", cal, cal,  cal, cal);
+        assertFalse(fLoc.toString().equals(fNoL.toString()));
 
         fLoc = new Formatter(Locale.US);
         fNoL = new Formatter(Locale.US);
@@ -107,31 +98,25 @@
                 "%+ a", "%+ A", "%-03e", "%-03E", "%-03g", "%-03G", "%-03f",
                 "%-03a", "%-03A" };
         for (int i = 0; i < illFlags.length; i++) {
-            if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
-                try {
-                    fLoc = new Formatter(Locale.US);
-                    fLoc.format(Locale.FRANCE, illFlags[i], 1.23d);
-                    fail("should throw IllegalFormatFlagsException");
-                } catch (IllegalFormatFlagsException expected) {
-                }
+            try {
+                fLoc = new Formatter(Locale.US);
+                fLoc.format(Locale.FRANCE, illFlags[i], 1.23d);
+                fail("should throw IllegalFormatFlagsException");
+            } catch (IllegalFormatFlagsException expected) {
             }
-
-            if (Support_Locale.isLocaleAvailable(Locale.CANADA)) {
-                try {
-                    fLoc = new Formatter(Locale.CANADA);
-                    fLoc.format(Locale.GERMAN, illFlags[i], (Double) null);
-                    fail("should throw IllegalFormatFlagsException");
-                } catch (IllegalFormatFlagsException expected) {
-                }
+            try {
+                fLoc = new Formatter(Locale.CANADA);
+                fLoc.format(Locale.GERMAN, illFlags[i], (Double) null);
+                fail("should throw IllegalFormatFlagsException");
+            } catch (IllegalFormatFlagsException expected) {
             }
         }
-        fLoc.close();
 
-        if (Support_Locale.isLocaleAvailable(Locale.GERMAN)) {
-            try {
-                fLoc.format(Locale.GERMAN, "%f", val);
-            } catch (FormatterClosedException expected) {
-            }
+        fLoc.close();
+        try {
+            fLoc.format(Locale.GERMAN, "%f", val);
+            fail();
+        } catch (FormatterClosedException expected) {
         }
     }
 }
diff --git a/luni/src/test/java/libcore/java/util/OldScannerTest.java b/luni/src/test/java/libcore/java/util/OldScannerTest.java
index 9bac1f4..4f63d92 100644
--- a/luni/src/test/java/libcore/java/util/OldScannerTest.java
+++ b/luni/src/test/java/libcore/java/util/OldScannerTest.java
@@ -15,7 +15,13 @@
  */
 package libcore.java.util;
 
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
 import java.io.StringReader;
 import java.net.InetSocketAddress;
 import java.nio.CharBuffer;
@@ -31,12 +37,10 @@
 
 public final class OldScannerTest extends TestCase {
 
-    private Scanner s;
-
     public void test_findWithinHorizon_Ljava_lang_StringI() {
         // This method searches through the input up to the specified search
         // horizon(exclusive).
-        s = new Scanner("123test");
+        Scanner s = new Scanner("123test");
         String result = s.findWithinHorizon("\\p{Lower}", 5);
         assertEquals("t", result);
         MatchResult mresult = s.match();
@@ -265,30 +269,7 @@
     }
 
     public void test_findInLine_LString() {
-        s = new Scanner("test");
-        try {
-            s.findInLine((String) null);
-            fail("Should throw NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
-
-        s.close();
-        try {
-            s.findInLine((String) null);
-            fail("Should throw NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
-        try {
-            s.findInLine("test");
-            fail("Should throw IllegalStateException");
-        } catch (IllegalStateException e) {
-            // exptected
-        }
-
-        s = new Scanner("");
-
+        Scanner s = new Scanner("");
         String result = s.findInLine("^");
         assertEquals("", result);
         MatchResult matchResult = s.match();
@@ -325,8 +306,7 @@
         try {
             matchResult = s.match();
             fail("Should throw IllegalStateException");
-        } catch (IllegalStateException e) {
-            // expected
+        } catch (IllegalStateException expected) {
         }
         assertEquals(0, matchResult.start());
         assertEquals(4, matchResult.end());
@@ -392,105 +372,6 @@
         result = s.findInLine("est");
     }
 
-    public void test_skip_LPattern() {
-        s = new Scanner("test");
-        try {
-            s.skip((String) null);
-            fail("Should throw NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
-
-        // If pattern does not match, NoSuchElementException will be thrown out.
-        s = new Scanner("1234");
-        try {
-            s.skip(Pattern.compile("\\p{Lower}"));
-            fail("Should throw NoSuchElementException");
-        } catch (NoSuchElementException e) {
-            // expected
-        }
-        // Then, no matchResult will be thrown out.
-        try {
-            s.match();
-            fail("Should throw IllegalStateException");
-        } catch (IllegalStateException e) {
-            // expected
-        }
-
-        s.skip(Pattern.compile("\\p{Digit}"));
-        MatchResult matchResult = s.match();
-        assertEquals(0, matchResult.start());
-        assertEquals(1, matchResult.end());
-
-        s.skip(Pattern.compile("\\p{Digit}+"));
-        matchResult = s.match();
-        assertEquals(1, matchResult.start());
-        assertEquals(4, matchResult.end());
-
-        s.close();
-        try {
-            s.skip(Pattern.compile("test"));
-            fail("Should throw IllegalStateException");
-        } catch (IllegalStateException e) {
-            // expected
-        }
-
-        MockStringReader2Read reader = new MockStringReader2Read("test");
-        s = new Scanner(reader);
-        try {
-            s.skip(Pattern.compile("\\p{Digit}{4}"));
-            fail("Should throw NoSuchElementException");
-        } catch (NoSuchElementException e) {
-            // expected
-        }
-        try {
-            s.match();
-            fail("Should throw IllegalStateException");
-        } catch (IllegalStateException e) {
-            // expected
-        }
-        s.skip(Pattern.compile("\\p{Digit}{3}\\p{Lower}"));
-        matchResult = s.match();
-        assertEquals(0, matchResult.start());
-        assertEquals(4, matchResult.end());
-
-        s.close();
-        try {
-            s.skip((Pattern) null);
-            fail("Should throw IllegalStateException");
-        } catch (IllegalStateException e) {
-            // expected
-        }
-
-        StringBuilder stringBuilder = new StringBuilder();
-        char [] chars = new char[1024];
-        Arrays.fill(chars, 'a');
-        stringBuilder.append(chars);
-        stringBuilder.append('3');
-        s = new Scanner(stringBuilder.toString());
-        s.skip(Pattern.compile("\\p{Lower}+\\p{Digit}"));
-        matchResult = s.match();
-        assertEquals(0, matchResult.start());
-        assertEquals(1025, matchResult.end());
-
-        // Large amount of input may be cached
-        chars = new char[102400];
-        Arrays.fill(chars, 'a');
-        stringBuilder = new StringBuilder();
-        stringBuilder.append(chars);
-        s = new Scanner(stringBuilder.toString());
-        s.skip(Pattern.compile(".*"));
-        matchResult = s.match();
-        assertEquals(0, matchResult.start());
-        assertEquals(102400, matchResult.end());
-
-        // skip something without risking a NoSuchElementException
-        s.skip(Pattern.compile("[ \t]*"));
-        matchResult = s.match();
-        assertEquals(102400, matchResult.start());
-        assertEquals(102400, matchResult.end());
-    }
-
     public void test_Constructor_LReadableByteChannel() throws IOException {
         ServerSocketChannel ssc = ServerSocketChannel.open();
         ssc.socket().bind(null);
@@ -529,27 +410,33 @@
         }
     }
 
-    private static class MockStringReader2Read extends StringReader {
-        private int timesRead = 1;
+  // http://code.google.com/p/android/issues/detail?id=57050
+  public void testPerformance() throws Exception {
+    int count = 100000;
 
-        public MockStringReader2Read(String param) {
-            super(param);
-        }
-
-        public int read(CharBuffer target) throws IOException {
-            if (timesRead == 1) {
-                target.append('1');
-                target.append('2');
-                target.append('3');
-                timesRead++;
-                return 3;
-            } else if (timesRead == 2) {
-                target.append('t');
-                timesRead++;
-                return 1;
-            } else {
-                throw new IOException();
-            }
-        }
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(baos));
+    for (int i = 0; i < count; ++i) {
+      out.write(Integer.toString(123) + " ");
     }
+    out.close();
+
+    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+    bais.mark(-1);
+
+    Scanner s = new Scanner(new BufferedReader(new InputStreamReader(bais)));
+    for (int i = 0; i < count; ++i) {
+      if (s.nextInt() != 123) {
+        fail();
+      }
+    }
+
+    bais.reset();
+    s = new Scanner(new BufferedReader(new InputStreamReader(bais)));
+    for (int i = 0; i < count; ++i) {
+      if (s.nextFloat() != 123.0) {
+        fail();
+      }
+    }
+  }
 }
diff --git a/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java b/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java
index 03a49ca..713e1b5 100644
--- a/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java
@@ -22,7 +22,6 @@
 import java.util.Locale;
 import java.util.TimeZone;
 import junit.framework.TestCase;
-import tests.support.Support_Locale;
 
 public class OldTimeZoneTest extends TestCase {
 
@@ -93,10 +92,7 @@
     public void test_getDisplayNameLjava_util_Locale() {
         TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
         assertEquals("Pacific Standard Time", tz.getDisplayName(new Locale("US")));
-        if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
-            // BEGIN android-note: RI has "Heure", CLDR/ICU has "heure".
-            assertEquals("heure normale du Pacifique", tz.getDisplayName(Locale.FRANCE));
-        }
+        assertEquals("heure normale du Pacifique", tz.getDisplayName(Locale.FRANCE));
     }
 
     public void test_getDisplayNameZI() {
@@ -112,16 +108,12 @@
         TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
         assertEquals("PST",                   tz.getDisplayName(false, 0, Locale.US));
         assertEquals("Pacific Daylight Time", tz.getDisplayName(true,  1, Locale.US));
-        if (Support_Locale.isLocaleAvailable(Locale.UK)) {
-            assertEquals("Pacific Standard Time", tz.getDisplayName(false, 1, Locale.UK));
-        }
-        if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
-            // RI always returns short time zone name as "PST"
-            // ICU zone/root.txt patched to allow metazone names.
-            assertEquals("PST",             tz.getDisplayName(false, 0, Locale.FRANCE));
-            assertEquals("heure avanc\u00e9e du Pacifique", tz.getDisplayName(true,  1, Locale.FRANCE));
-            assertEquals("heure normale du Pacifique", tz.getDisplayName(false, 1, Locale.FRANCE));
-        }
+        assertEquals("Pacific Standard Time", tz.getDisplayName(false, 1, Locale.UK));
+        // RI always returns short time zone name as "PST"
+        // ICU zone/root.txt patched to allow metazone names.
+        assertEquals("PST",             tz.getDisplayName(false, 0, Locale.FRANCE));
+        assertEquals("heure avanc\u00e9e du Pacifique", tz.getDisplayName(true,  1, Locale.FRANCE));
+        assertEquals("heure normale du Pacifique", tz.getDisplayName(false, 1, Locale.FRANCE));
     }
 
     public void test_getID() {
diff --git a/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java b/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java
index 8d6e186..deb0626 100644
--- a/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java
+++ b/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java
@@ -421,44 +421,6 @@
 
     }
 
-    // BEGIN android-note
-    // Test took ages, now going in steps of 16 code points to speed things up.
-    // END android-note
-    public void testAllCodePoints() {
-        // Regression for HARMONY-3145
-        int[] codePoint = new int[1];
-        Pattern p = Pattern.compile("(\\p{all})+");
-        boolean res = true;
-        int cnt = 0;
-        String s;
-        for (int i = 0; i < 0x110000; i = i + 0x10) {
-            codePoint[0] = i;
-            s = new String(codePoint, 0, 1);
-            if (!s.matches(p.toString())) {
-                cnt++;
-                res = false;
-            }
-        }
-        assertTrue(res);
-        assertEquals(0, cnt);
-
-        p = Pattern.compile("(\\P{all})+");
-        res = true;
-        cnt = 0;
-
-        for (int i = 0; i < 0x110000; i = i + 0x10) {
-            codePoint[0] = i;
-            s = new String(codePoint, 0, 1);
-            if (!s.matches(p.toString())) {
-                cnt++;
-                res = false;
-            }
-        }
-
-        assertFalse(res);
-        assertEquals(0x110000 / 0x10, cnt);
-    }
-
     public void test_regionStart() {
         String testPattern = "(abb)";
         String testString = "cccabbabbabbabbabb";
diff --git a/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java b/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java
index 37d1248..2e32f7d 100644
--- a/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java
@@ -19,6 +19,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.EOFException;
+import java.io.InputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PipedInputStream;
@@ -30,13 +31,15 @@
 import java.util.concurrent.Executors;
 import java.util.zip.Deflater;
 import java.util.zip.DeflaterOutputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
 import java.util.zip.InflaterInputStream;
 import junit.framework.TestCase;
 
 public class DeflaterOutputStreamTest extends TestCase {
 
     public void testSyncFlushEnabled() throws Exception {
-        InflaterInputStream in = createInflaterStream(true);
+        InputStream in = createInflaterStream(DeflaterOutputStream.class, true);
         assertEquals(1, in.read());
         assertEquals(2, in.read());
         assertEquals(3, in.read());
@@ -44,7 +47,7 @@
     }
 
     public void testSyncFlushDisabled() throws Exception {
-        InflaterInputStream in = createInflaterStream(false);
+        InputStream in = createInflaterStream(DeflaterOutputStream.class, false);
         try {
             in.read();
             fail();
@@ -65,14 +68,21 @@
      * way demonstrate that data is unavailable. Ie. other techniques will cause
      * the dry read to block indefinitely.
      */
-    private InflaterInputStream createInflaterStream(final boolean flushing) throws Exception {
+    static InputStream createInflaterStream(final Class<?> c, final boolean flushing) throws Exception {
         ExecutorService executor = Executors.newSingleThreadExecutor();
         final PipedOutputStream pout = new PipedOutputStream();
         PipedInputStream pin = new PipedInputStream(pout);
 
         executor.submit(new Callable<Void>() {
             public Void call() throws Exception {
-                OutputStream out = new DeflaterOutputStream(pout, flushing);
+                OutputStream out;
+                if (c == DeflaterOutputStream.class) {
+                    out = new DeflaterOutputStream(pout, flushing);
+                } else if (c == GZIPOutputStream.class) {
+                    out = new GZIPOutputStream(pout, flushing);
+                } else {
+                    throw new AssertionError();
+                }
                 out.write(1);
                 out.write(2);
                 out.write(3);
@@ -82,7 +92,13 @@
         }).get();
         executor.shutdown();
 
-        return new InflaterInputStream(pin);
+        if (c == DeflaterOutputStream.class) {
+            return new InflaterInputStream(pin);
+        } else if (c == GZIPOutputStream.class) {
+            return new GZIPInputStream(pin);
+        } else {
+            throw new AssertionError();
+        }
     }
 
     /**
@@ -146,5 +162,9 @@
         // during the test, since that would lead to the results being
         // flushed even without SYNC_FLUSH being used
         assertFalse(def.finished());
+
+        // Quieten CloseGuard.
+        def.end();
+        iis.close();
     }
 }
diff --git a/luni/src/test/java/libcore/java/util/zip/GZIPOutputStreamTest.java b/luni/src/test/java/libcore/java/util/zip/GZIPOutputStreamTest.java
index a61880f..55e45bc 100644
--- a/luni/src/test/java/libcore/java/util/zip/GZIPOutputStreamTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/GZIPOutputStreamTest.java
@@ -25,26 +25,46 @@
 import java.util.Random;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
+import java.util.zip.InflaterInputStream;
 import junit.framework.TestCase;
 
 public final class GZIPOutputStreamTest extends TestCase {
-    public void testShortMessage() throws IOException {
-        byte[] data = gzip(("Hello World").getBytes("UTF-8"));
-        assertEquals("[31, -117, 8, 0, 0, 0, 0, 0, 0, 0, -13, 72, -51, -55, -55, 87, 8, -49, " +
-                "47, -54, 73, 1, 0, 86, -79, 23, 74, 11, 0, 0, 0]", Arrays.toString(data));
-    }
+  public void testShortMessage() throws IOException {
+    byte[] data = gzip(("Hello World").getBytes("UTF-8"));
+    assertEquals("[31, -117, 8, 0, 0, 0, 0, 0, 0, 0, -13, 72, -51, -55, -55, 87, 8, -49, " +
+                 "47, -54, 73, 1, 0, 86, -79, 23, 74, 11, 0, 0, 0]", Arrays.toString(data));
+  }
 
-    public void testLongMessage() throws IOException {
-        byte[] data = new byte[1024 * 1024];
-        new Random().nextBytes(data);
-        assertTrue(Arrays.equals(data, GZIPInputStreamTest.gunzip(gzip(data))));
-    }
+  public void testLongMessage() throws IOException {
+    byte[] data = new byte[1024 * 1024];
+    new Random().nextBytes(data);
+    assertTrue(Arrays.equals(data, GZIPInputStreamTest.gunzip(gzip(data))));
+  }
 
-    public static byte[] gzip(byte[] bytes) throws IOException {
-        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
-        OutputStream gzippedOut = new GZIPOutputStream(bytesOut);
-        gzippedOut.write(bytes);
-        gzippedOut.close();
-        return bytesOut.toByteArray();
+  public static byte[] gzip(byte[] bytes) throws IOException {
+    ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+    OutputStream gzippedOut = new GZIPOutputStream(bytesOut);
+    gzippedOut.write(bytes);
+    gzippedOut.close();
+    return bytesOut.toByteArray();
+  }
+
+  public void testSyncFlushEnabled() throws Exception {
+    InputStream in = DeflaterOutputStreamTest.createInflaterStream(GZIPOutputStream.class, true);
+    assertEquals(1, in.read());
+    assertEquals(2, in.read());
+    assertEquals(3, in.read());
+    in.close();
+  }
+
+  public void testSyncFlushDisabled() throws Exception {
+    InputStream in = DeflaterOutputStreamTest.createInflaterStream(GZIPOutputStream.class, false);
+    try {
+      in.read();
+      fail();
+    } catch (IOException expected) {
     }
+    in.close();
+  }
+
 }
diff --git a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
index b1fa33c..cad881b 100644
--- a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
@@ -316,7 +316,7 @@
         return sb.toString();
     }
 
-    public void testComment() throws Exception {
+    public void testComments() throws Exception {
         String expectedFileComment = "1 \u0666 2";
         String expectedEntryComment = "a \u0666 b";
 
@@ -361,11 +361,23 @@
         out.close();
 
         ZipFile zipFile = new ZipFile(file);
-        // TODO: there's currently no API for reading the file comment --- strings(1) the file?
+        assertEquals(expectedFileComment, zipFile.getComment());
         assertEquals(expectedEntryComment, zipFile.getEntry("a").getComment());
         zipFile.close();
     }
 
+    public void test_getComment_unset() throws Exception {
+        File file = createTemporaryZipFile();
+        ZipOutputStream out = createZipOutputStream(file);
+        ZipEntry ze = new ZipEntry("test entry");
+        ze.setComment("per-entry comment");
+        out.putNextEntry(ze);
+        out.close();
+
+        ZipFile zipFile = new ZipFile(file);
+        assertEquals(null, zipFile.getComment());
+    }
+
     public void testNameLengthChecks() throws IOException {
         // Is entry name length checking done on bytes or characters?
         // Really it should be bytes, but the RI only checks characters at construction time.
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index 4054813..dac43a2 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -20,6 +20,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.math.BigInteger;
+import java.nio.ByteBuffer;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.Key;
@@ -91,28 +92,28 @@
         IS_UNLIMITED = is_unlimited;
     }
 
-    private static boolean isUnsupported(String algorithm, String provider) {
+    private static boolean isSupported(String algorithm, String provider) {
         if (algorithm.equals("RC2")) {
-            return true;
+            return false;
         }
         if (algorithm.equals("PBEWITHMD5ANDRC2")) {
-            return true;
+            return false;
         }
         if (algorithm.startsWith("PBEWITHSHA1ANDRC2")) {
-            return true;
+            return false;
         }
         if (algorithm.equals("PBEWITHSHAAND40BITRC2-CBC")) {
-            return true;
+            return false;
         }
         if (algorithm.equals("PBEWITHSHAAND128BITRC2-CBC")) {
-            return true;
+            return false;
         }
         if (algorithm.equals("PBEWITHSHAANDTWOFISH-CBC")) {
-            return true;
+            return false;
         }
         if (!IS_UNLIMITED) {
             if (algorithm.equals("PBEWITHMD5ANDTRIPLEDES")) {
-                return true;
+                return false;
             }
         }
         // stream modes CFB, CTR, CTS, OFB with PKCS5Padding don't really make sense
@@ -121,25 +122,25 @@
              || algorithm.equals("AES/CTR/PKCS5PADDING")
              || algorithm.equals("AES/CTS/PKCS5PADDING")
              || algorithm.equals("AES/OFB/PKCS5PADDING"))) {
-            return true;
+            return false;
         }
-        return false;
+        return true;
     }
 
-    private static boolean isUnsupportedForWrapping(String algorithm) {
+    private static boolean isSupportedForWrapping(String algorithm) {
         if (isOnlyWrappingAlgorithm(algorithm)) {
-            return false;
+            return true;
         }
         // http://b/9097343 RSA with NoPadding won't work since
         // leading zeroes in the underlying key material are lost.
         if (algorithm.equals("RSA/ECB/NOPADDING")) {
-            return true;
+            return false;
         }
         // AESWRAP should be used instead, fails with BC and SunJCE otherwise.
         if (algorithm.startsWith("AES")) {
-            return true;
+            return false;
         }
-        return false;
+        return true;
     }
 
     private synchronized static int getEncryptMode(String algorithm) throws Exception {
@@ -796,7 +797,7 @@
     private void test_Cipher(Cipher c) throws Exception {
         String algorithm = c.getAlgorithm().toUpperCase(Locale.US);
         String providerName = c.getProvider().getName();
-        if (isUnsupported(algorithm, providerName)) {
+        if (!isSupported(algorithm, providerName)) {
             return;
         }
         String cipherID = algorithm + ":" + providerName;
@@ -832,7 +833,7 @@
         assertNull(cipherID, c.getExemptionMechanism());
 
         // Test wrapping a key.  Every cipher should be able to wrap. Except those that can't.
-        if (!isUnsupportedForWrapping(algorithm)) {
+        if (isSupportedForWrapping(algorithm)) {
             // Generate a small SecretKey for AES.
             KeyGenerator kg = KeyGenerator.getInstance("AES");
             kg.init(128);
@@ -2164,6 +2165,12 @@
 
         c.init(Cipher.DECRYPT_MODE, key, spec);
 
+        try {
+            c.updateAAD(new byte[8]);
+            fail("Cipher should not support AAD");
+        } catch (UnsupportedOperationException expected) {
+        }
+
         byte[] emptyPlainText = c.doFinal(emptyCipherText);
         assertEquals(Arrays.toString(EmptyArray.BYTE), Arrays.toString(emptyPlainText));
 
@@ -2257,6 +2264,82 @@
         }
     }
 
+    public void testCipher_updateAAD_BeforeInit_Failure() throws Exception {
+        Cipher c = Cipher.getInstance("AES/ECB/NoPadding");
+
+        try {
+            c.updateAAD((byte[]) null);
+            fail("should not be able to call updateAAD before Cipher is initialized");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            c.updateAAD((ByteBuffer) null);
+            fail("should not be able to call updateAAD before Cipher is initialized");
+        } catch (IllegalStateException expected) {
+        }
+
+        try {
+            c.updateAAD(new byte[8]);
+            fail("should not be able to call updateAAD before Cipher is initialized");
+        } catch (IllegalStateException expected) {
+        }
+
+        try {
+            c.updateAAD(null, 0, 8);
+            fail("should not be able to call updateAAD before Cipher is initialized");
+        } catch (IllegalStateException expected) {
+        }
+
+        ByteBuffer bb = ByteBuffer.allocate(8);
+        try {
+            c.updateAAD(bb);
+            fail("should not be able to call updateAAD before Cipher is initialized");
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testCipher_updateAAD_AfterInit_Failure() throws Exception {
+        Cipher c = Cipher.getInstance("AES/ECB/NoPadding");
+        c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[128 / 8], "AES"));
+
+        try {
+            c.updateAAD((byte[]) null);
+            fail("should not be able to call updateAAD with null input");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            c.updateAAD((ByteBuffer) null);
+            fail("should not be able to call updateAAD with null input");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            c.updateAAD(null, 0, 8);
+            fail("should not be able to call updateAAD with null input");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            c.updateAAD(new byte[8], -1, 7);
+            fail("should not be able to call updateAAD with invalid offset");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            c.updateAAD(new byte[8], 0, -1);
+            fail("should not be able to call updateAAD with negative length");
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            c.updateAAD(new byte[8], 0, 8 + 1);
+            fail("should not be able to call updateAAD with too large length");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
     public void testCipher_ShortBlock_Failure() throws Exception {
         for (String provider : AES_PROVIDERS) {
             testCipher_ShortBlock_Failure(provider);
diff --git a/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java b/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java
index 7519aab..ef5adc9 100644
--- a/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java
@@ -23,6 +23,7 @@
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
 import junit.framework.TestCase;
+import libcore.java.security.StandardNames;
 
 public class SecretKeyFactoryTest extends TestCase {
 
@@ -107,13 +108,14 @@
     }
 
     public void test_PBKDF2_b3059950() throws Exception {
-        test_PBKDF2(PASSWORD, SALT, ITERATIONS, KEY_LENGTH,
-                    new byte[] {
+        byte[] expected = new byte[] {
                         (byte)0x70, (byte)0x74, (byte)0xdb, (byte)0x72,
                         (byte)0x35, (byte)0xd4, (byte)0x11, (byte)0x68,
                         (byte)0x83, (byte)0x7c, (byte)0x14, (byte)0x1f,
                         (byte)0xf6, (byte)0x4a, (byte)0xb0, (byte)0x54
-                    });
+                    };
+        test_PBKDF2_UTF8(PASSWORD, SALT, ITERATIONS, KEY_LENGTH, expected);
+        test_PBKDF2_8BIT(PASSWORD, SALT, ITERATIONS, KEY_LENGTH, expected);
     }
 
     /**
@@ -133,7 +135,8 @@
             (byte)0xD1, (byte)0xDA, (byte)0xA7, (byte)0x86,
             (byte)0x15, (byte)0xF2, (byte)0x87, (byte)0xE6
         };
-        test_PBKDF2(password, salt, iterations, keyLength, expected);
+        test_PBKDF2_UTF8(password, salt, iterations, keyLength, expected);
+        test_PBKDF2_8BIT(password, salt, iterations, keyLength, expected);
     }
 
     /**
@@ -156,11 +159,50 @@
             (byte)0x85, (byte)0x10, (byte)0x85, (byte)0x86, (byte)0x07, (byte)0x12,
             (byte)0x63, (byte)0x80, (byte)0xcc, (byte)0x47, (byte)0xab, (byte)0x2d
         };
-        test_PBKDF2(password, salt, iterations, keyLength, expected);
+        test_PBKDF2_UTF8(password, salt, iterations, keyLength, expected);
+        test_PBKDF2_8BIT(password, salt, iterations, keyLength, expected);
     }
 
-    private void test_PBKDF2(char[] password, byte[] salt, int iterations, int keyLength,
-                             byte[] expected) throws Exception {
+   /**
+    * Unicode Test vector for b/8312059.
+    *
+    * See also https://code.google.com/p/android/issues/detail?id=40578
+    */
+    public void test_PBKDF2_b8312059() throws Exception {
+
+        char[] password = "\u0141\u0142".toCharArray();
+        byte[] salt = "salt".getBytes();
+        int iterations = 4096;
+        int keyLength = 160;
+        byte[] expected_utf8 = new byte[] {
+            (byte)0x4c, (byte)0xe0, (byte)0x6a, (byte)0xb8, (byte)0x48, (byte)0x04,
+            (byte)0xb7, (byte)0xe7, (byte)0x72, (byte)0xf2, (byte)0xaf, (byte)0x5e,
+            (byte)0x54, (byte)0xe9, (byte)0x03, (byte)0xad, (byte)0x59, (byte)0x64,
+            (byte)0x8b, (byte)0xab
+        };
+        byte[] expected_8bit = new byte[] {
+            (byte)0x6e, (byte)0x43, (byte)0xe0, (byte)0x18, (byte)0xc5, (byte)0x50,
+            (byte)0x0d, (byte)0xa7, (byte)0xfe, (byte)0x7a, (byte)0x44, (byte)0x4d,
+            (byte)0x99, (byte)0x5d, (byte)0x8c, (byte)0xae, (byte)0xc1, (byte)0xc9,
+            (byte)0x17, (byte)0xce
+        };
+        test_PBKDF2_UTF8(password, salt, iterations, keyLength, expected_utf8);
+        test_PBKDF2_8BIT(password, salt, iterations, keyLength, expected_8bit);
+    }
+
+    private void test_PBKDF2_8BIT(char[] password, byte[] salt, int iterations, int keyLength,
+                                  byte[] expected) throws Exception {
+        if (!StandardNames.IS_RI) {
+            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1And8bit");
+            KeySpec ks = new PBEKeySpec(password, salt, iterations, keyLength);
+            SecretKey key = factory.generateSecret(ks);
+            assertTrue(Arrays.equals(expected, key.getEncoded()));
+        }
+
+    }
+
+    private void test_PBKDF2_UTF8(char[] password, byte[] salt, int iterations, int keyLength,
+                                  byte[] expected) throws Exception {
         SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
         KeySpec ks = new PBEKeySpec(password, salt, iterations, keyLength);
         SecretKey key = factory.generateSecret(ks);
diff --git a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
index 69ae1c1..e1c9fe3 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
@@ -19,7 +19,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.math.BigInteger;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
 import java.security.Principal;
 import java.security.PublicKey;
 import java.security.cert.CertificateFactory;
@@ -301,7 +301,7 @@
     }
 
     X509Certificate parseCertificate(String encoded) throws Exception {
-        InputStream in = new ByteArrayInputStream(encoded.getBytes(Charsets.US_ASCII));
+        InputStream in = new ByteArrayInputStream(encoded.getBytes(StandardCharsets.US_ASCII));
         return (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(in);
     }
 
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index 7a1465e..de12967 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -1215,7 +1215,7 @@
         client.startHandshake();
 
         // Reflection is used so this can compile on the RI
-        String expectedClassName = "org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl";
+        String expectedClassName = "com.android.org.conscrypt.OpenSSLSocketImpl";
         Class actualClass = client.getClass();
         assertEquals(expectedClassName, actualClass.getName());
         Method setSoWriteTimeout = actualClass.getMethod("setSoWriteTimeout",
diff --git a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
index e37ed1f..7ee5778 100644
--- a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
+++ b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
@@ -19,10 +19,12 @@
 import java.io.ByteArrayInputStream;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
+import java.util.Arrays;
 import javax.security.auth.x500.X500Principal;
 import junit.framework.TestCase;
 import libcore.util.SerializationTester;
 
+
 public class X500PrincipalTest extends TestCase {
 
     public void testSerialization() {
@@ -90,4 +92,23 @@
                      certBC.getSubjectX500Principal().getName(X500Principal.CANONICAL));
 
     }
+
+    // http://code.google.com/p/android/issues/detail?id=21531
+    // http://b/5580664
+    public void testIA5StringEncodings() {
+        testIA5StringEncoding("emailAddress=root@android.com",
+                              new byte[] { 48, 33, 49, 31, 48, 29, 6, 9, 42, -122, 72, -122, -9, 13, 1, 9, 1, 22, 16, 114, 111, 111, 116, 64, 97, 110, 100, 114, 111, 105, 100, 46, 99, 111, 109 });
+        testIA5StringEncoding("dc=com",
+                              new byte[] { 48, 21, 49, 19, 48, 17, 6, 10, 9, -110, 38, -119, -109, -14, 44, 100, 1, 25, 22, 3, 99, 111, 109 });
+    }
+
+    private void testIA5StringEncoding(String name, byte[] expectedEncoded) {
+        X500Principal original = new X500Principal(name);
+
+        byte[] actualEncoded = original.getEncoded();
+        assertEquals(Arrays.toString(expectedEncoded), Arrays.toString(actualEncoded));
+
+        X500Principal decoded = new X500Principal(actualEncoded);
+        assertEquals(original, decoded);
+    }
 }
diff --git a/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java b/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java
deleted file mode 100644
index 133924e..0000000
--- a/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java
+++ /dev/null
@@ -1,1886 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.net.http;
-
-import com.google.mockwebserver.MockResponse;
-import com.google.mockwebserver.MockWebServer;
-import com.google.mockwebserver.RecordedRequest;
-import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.lang.reflect.InvocationHandler;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.CookieHandler;
-import java.net.CookieManager;
-import java.net.HttpCookie;
-import java.net.HttpURLConnection;
-import java.net.ResponseCache;
-import java.net.SecureCacheResponse;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Deque;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.zip.GZIPOutputStream;
-import javax.net.ssl.HttpsURLConnection;
-import junit.framework.TestCase;
-import libcore.javax.net.ssl.TestSSLContext;
-import tests.io.MockOs;
-
-public final class HttpResponseCacheTest extends TestCase {
-    private MockWebServer server = new MockWebServer();
-    private HttpResponseCache cache;
-    private final MockOs mockOs = new MockOs();
-    private final CookieManager cookieManager = new CookieManager();
-
-    @Override protected void setUp() throws Exception {
-        super.setUp();
-
-        String tmp = System.getProperty("java.io.tmpdir");
-        File cacheDir = new File(tmp, "HttpCache-" + UUID.randomUUID());
-        cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE);
-        ResponseCache.setDefault(cache);
-        mockOs.install();
-        CookieHandler.setDefault(cookieManager);
-    }
-
-    @Override protected void tearDown() throws Exception {
-        mockOs.uninstall();
-        server.shutdown();
-        ResponseCache.setDefault(null);
-        cache.getCache().delete();
-        CookieHandler.setDefault(null);
-        super.tearDown();
-    }
-
-    /**
-     * Test that response caching is consistent with the RI and the spec.
-     * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4
-     */
-    public void testResponseCachingByResponseCode() throws Exception {
-        // Test each documented HTTP/1.1 code, plus the first unused value in each range.
-        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
-
-        // We can't test 100 because it's not really a response.
-        // assertCached(false, 100);
-        assertCached(false, 101);
-        assertCached(false, 102);
-        assertCached(true,  200);
-        assertCached(false, 201);
-        assertCached(false, 202);
-        assertCached(true,  203);
-        assertCached(false, 204);
-        assertCached(false, 205);
-        assertCached(false, 206); // we don't cache partial responses
-        assertCached(false, 207);
-        assertCached(true,  300);
-        assertCached(true,  301);
-        for (int i = 302; i <= 308; ++i) {
-            assertCached(false, i);
-        }
-        for (int i = 400; i <= 406; ++i) {
-            assertCached(false, i);
-        }
-        // (See test_responseCaching_407.)
-        assertCached(false, 408);
-        assertCached(false, 409);
-        // (See test_responseCaching_410.)
-        for (int i = 411; i <= 418; ++i) {
-            assertCached(false, i);
-        }
-        for (int i = 500; i <= 506; ++i) {
-            assertCached(false, i);
-        }
-    }
-
-    /**
-     * Response code 407 should only come from proxy servers. Android's client
-     * throws if it is sent by an origin server.
-     */
-    public void testOriginServerSends407() throws Exception {
-        server.enqueue(new MockResponse().setResponseCode(407));
-        server.play();
-
-        URL url = server.getUrl("/");
-        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-        try {
-            conn.getResponseCode();
-            fail();
-        } catch (IOException expected) {
-        }
-    }
-
-    public void test_responseCaching_410() throws Exception {
-        // the HTTP spec permits caching 410s, but the RI doesn't.
-        assertCached(true, 410);
-    }
-
-    private void assertCached(boolean shouldPut, int responseCode) throws Exception {
-        server = new MockWebServer();
-        MockResponse response = new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setResponseCode(responseCode)
-                .setBody("ABCDE")
-                .addHeader("WWW-Authenticate: challenge");
-        if (responseCode == HttpURLConnection.HTTP_PROXY_AUTH) {
-            response.addHeader("Proxy-Authenticate: Basic realm=\"protected area\"");
-        } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
-            response.addHeader("WWW-Authenticate: Basic realm=\"protected area\"");
-        }
-        server.enqueue(response);
-        server.play();
-
-        URL url = server.getUrl("/");
-        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-        assertEquals(responseCode, conn.getResponseCode());
-
-        // exhaust the content stream
-        readAscii(conn);
-
-        CacheResponse cached = cache.get(url.toURI(), "GET",
-                Collections.<String, List<String>>emptyMap());
-        if (shouldPut) {
-            assertNotNull(Integer.toString(responseCode), cached);
-            cached.getBody().close();
-        } else {
-            assertNull(Integer.toString(responseCode), cached);
-        }
-        server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers
-    }
-
-    /**
-     * Test that we can interrogate the response when the cache is being
-     * populated. http://code.google.com/p/android/issues/detail?id=7787
-     */
-    public void testResponseCacheCallbackApis() throws Exception {
-        final String body = "ABCDE";
-        final AtomicInteger cacheCount = new AtomicInteger();
-
-        server.enqueue(new MockResponse()
-                .setStatus("HTTP/1.1 200 Fantastic")
-                .addHeader("fgh: ijk")
-                .setBody(body));
-        server.play();
-
-        ResponseCache.setDefault(new ResponseCache() {
-            @Override public CacheResponse get(URI uri, String requestMethod,
-                    Map<String, List<String>> requestHeaders) throws IOException {
-                return null;
-            }
-            @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException {
-                HttpURLConnection httpConnection = (HttpURLConnection) conn;
-                try {
-                    httpConnection.getRequestProperties();
-                    fail();
-                } catch (IllegalStateException expected) {
-                }
-                try {
-                    httpConnection.addRequestProperty("K", "V");
-                    fail();
-                } catch (IllegalStateException expected) {
-                }
-                assertEquals("HTTP/1.1 200 Fantastic", httpConnection.getHeaderField(null));
-                assertEquals(Arrays.asList("HTTP/1.1 200 Fantastic"),
-                        httpConnection.getHeaderFields().get(null));
-                assertEquals(200, httpConnection.getResponseCode());
-                assertEquals("Fantastic", httpConnection.getResponseMessage());
-                assertEquals(body.length(), httpConnection.getContentLength());
-                assertEquals("ijk", httpConnection.getHeaderField("fgh"));
-                try {
-                    httpConnection.getInputStream(); // the RI doesn't forbid this, but it should
-                    fail();
-                } catch (IOException expected) {
-                }
-                cacheCount.incrementAndGet();
-                return null;
-            }
-        });
-
-        URL url = server.getUrl("/");
-        URLConnection connection = url.openConnection();
-        assertEquals(body, readAscii(connection));
-        assertEquals(1, cacheCount.get());
-    }
-
-
-    public void testResponseCachingAndInputStreamSkipWithFixedLength() throws IOException {
-        testResponseCaching(TransferKind.FIXED_LENGTH);
-    }
-
-    public void testResponseCachingAndInputStreamSkipWithChunkedEncoding() throws IOException {
-        testResponseCaching(TransferKind.CHUNKED);
-    }
-
-    public void testResponseCachingAndInputStreamSkipWithNoLengthHeaders() throws IOException {
-        testResponseCaching(TransferKind.END_OF_STREAM);
-    }
-
-    /**
-     * HttpURLConnection.getInputStream().skip(long) causes ResponseCache corruption
-     * http://code.google.com/p/android/issues/detail?id=8175
-     */
-    private void testResponseCaching(TransferKind transferKind) throws IOException {
-        MockResponse response = new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setStatus("HTTP/1.1 200 Fantastic");
-        transferKind.setBody(response, "I love puppies but hate spiders", 1);
-        server.enqueue(response);
-        server.play();
-
-        // Make sure that calling skip() doesn't omit bytes from the cache.
-        HttpURLConnection urlConnection = (HttpURLConnection) server.getUrl("/").openConnection();
-        InputStream in = urlConnection.getInputStream();
-        assertEquals("I love ", readAscii(urlConnection, "I love ".length()));
-        reliableSkip(in, "puppies but hate ".length());
-        assertEquals("spiders", readAscii(urlConnection, "spiders".length()));
-        assertEquals(-1, in.read());
-        in.close();
-        assertEquals(1, cache.getWriteSuccessCount());
-        assertEquals(0, cache.getWriteAbortCount());
-
-        urlConnection = (HttpURLConnection) server.getUrl("/").openConnection(); // cached!
-        in = urlConnection.getInputStream();
-        assertEquals("I love puppies but hate spiders",
-                readAscii(urlConnection, "I love puppies but hate spiders".length()));
-        assertEquals(200, urlConnection.getResponseCode());
-        assertEquals("Fantastic", urlConnection.getResponseMessage());
-
-        assertEquals(-1, in.read());
-        in.close();
-        assertEquals(1, cache.getWriteSuccessCount());
-        assertEquals(0, cache.getWriteAbortCount());
-        assertEquals(2, cache.getRequestCount());
-        assertEquals(1, cache.getHitCount());
-    }
-
-    public void testSecureResponseCaching() throws IOException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setBody("ABC"));
-        server.play();
-
-        HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("ABC", readAscii(connection));
-
-        // OpenJDK 6 fails on this line, complaining that the connection isn't open yet
-        String suite = connection.getCipherSuite();
-        List<Certificate> localCerts = toListOrNull(connection.getLocalCertificates());
-        List<Certificate> serverCerts = toListOrNull(connection.getServerCertificates());
-        Principal peerPrincipal = connection.getPeerPrincipal();
-        Principal localPrincipal = connection.getLocalPrincipal();
-
-        connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached!
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("ABC", readAscii(connection));
-
-        assertEquals(2, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(1, cache.getHitCount());
-
-        assertEquals(suite, connection.getCipherSuite());
-        assertEquals(localCerts, toListOrNull(connection.getLocalCertificates()));
-        assertEquals(serverCerts, toListOrNull(connection.getServerCertificates()));
-        assertEquals(peerPrincipal, connection.getPeerPrincipal());
-        assertEquals(localPrincipal, connection.getLocalPrincipal());
-    }
-
-    public void testCacheReturnsInsecureResponseForSecureRequest() throws IOException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
-        server.enqueue(new MockResponse().setBody("ABC"));
-        server.enqueue(new MockResponse().setBody("DEF"));
-        server.play();
-
-        ResponseCache.setDefault(new InsecureResponseCache());
-
-        HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("ABC", readAscii(connection));
-
-        connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // not cached!
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("DEF", readAscii(connection));
-    }
-
-    public void testResponseCachingAndRedirects() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)
-                .addHeader("Location: /foo"));
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setBody("ABC"));
-        server.enqueue(new MockResponse().setBody("DEF"));
-        server.play();
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("ABC", readAscii(connection));
-
-        connection = server.getUrl("/").openConnection(); // cached!
-        assertEquals("ABC", readAscii(connection));
-
-        assertEquals(4, cache.getRequestCount()); // 2 requests + 2 redirects
-        assertEquals(2, cache.getNetworkCount());
-        assertEquals(2, cache.getHitCount());
-    }
-
-    public void testRedirectToCachedResult() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("ABC"));
-        server.enqueue(new MockResponse()
-                .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)
-                .addHeader("Location: /foo"));
-        server.enqueue(new MockResponse().setBody("DEF"));
-        server.play();
-
-        assertEquals("ABC", readAscii(server.getUrl("/foo").openConnection()));
-        RecordedRequest request1 = server.takeRequest();
-        assertEquals("GET /foo HTTP/1.1", request1.getRequestLine());
-        assertEquals(0, request1.getSequenceNumber());
-
-        assertEquals("ABC", readAscii(server.getUrl("/bar").openConnection()));
-        RecordedRequest request2 = server.takeRequest();
-        assertEquals("GET /bar HTTP/1.1", request2.getRequestLine());
-        assertEquals(1, request2.getSequenceNumber());
-
-        // an unrelated request should reuse the pooled connection
-        assertEquals("DEF", readAscii(server.getUrl("/baz").openConnection()));
-        RecordedRequest request3 = server.takeRequest();
-        assertEquals("GET /baz HTTP/1.1", request3.getRequestLine());
-        assertEquals(2, request3.getSequenceNumber());
-    }
-
-    public void testSecureResponseCachingAndRedirects() throws IOException {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)
-                .addHeader("Location: /foo"));
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .setBody("ABC"));
-        server.enqueue(new MockResponse().setBody("DEF"));
-        server.play();
-
-        HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("ABC", readAscii(connection));
-
-        connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached!
-        connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        assertEquals("ABC", readAscii(connection));
-
-        assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4
-        assertEquals(2, cache.getHitCount());
-    }
-
-    public void testResponseCacheRequestHeaders() throws IOException, URISyntaxException {
-        server.enqueue(new MockResponse().setBody("ABC"));
-        server.play();
-
-        final AtomicReference<Map<String, List<String>>> requestHeadersRef
-                = new AtomicReference<Map<String, List<String>>>();
-        ResponseCache.setDefault(new ResponseCache() {
-            @Override public CacheResponse get(URI uri, String requestMethod,
-                    Map<String, List<String>> requestHeaders) throws IOException {
-                requestHeadersRef.set(requestHeaders);
-                return null;
-            }
-            @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException {
-                return null;
-            }
-        });
-
-        URL url = server.getUrl("/");
-        URLConnection urlConnection = url.openConnection();
-        urlConnection.addRequestProperty("A", "android");
-        readAscii(urlConnection);
-        assertEquals(Arrays.asList("android"), requestHeadersRef.get().get("A"));
-    }
-
-
-    public void testServerDisconnectsPrematurelyWithContentLengthHeader() throws IOException {
-        testServerPrematureDisconnect(TransferKind.FIXED_LENGTH);
-    }
-
-    public void testServerDisconnectsPrematurelyWithChunkedEncoding() throws IOException {
-        testServerPrematureDisconnect(TransferKind.CHUNKED);
-    }
-
-    public void testServerDisconnectsPrematurelyWithNoLengthHeaders() throws IOException {
-        /*
-         * Intentionally empty. This case doesn't make sense because there's no
-         * such thing as a premature disconnect when the disconnect itself
-         * indicates the end of the data stream.
-         */
-    }
-
-    private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException {
-        MockResponse response = new MockResponse();
-        transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 16);
-        server.enqueue(truncateViolently(response, 16));
-        server.enqueue(new MockResponse().setBody("Request #2"));
-        server.play();
-
-        BufferedReader reader = new BufferedReader(new InputStreamReader(
-                server.getUrl("/").openConnection().getInputStream()));
-        assertEquals("ABCDE", reader.readLine());
-        try {
-            reader.readLine();
-            fail("This implementation silently ignored a truncated HTTP body.");
-        } catch (IOException expected) {
-        } finally {
-            reader.close();
-        }
-
-        assertEquals(1, cache.getWriteAbortCount());
-        assertEquals(0, cache.getWriteSuccessCount());
-        URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("Request #2", readAscii(connection));
-        assertEquals(1, cache.getWriteAbortCount());
-        assertEquals(1, cache.getWriteSuccessCount());
-    }
-
-    public void testClientPrematureDisconnectWithContentLengthHeader() throws IOException {
-        testClientPrematureDisconnect(TransferKind.FIXED_LENGTH);
-    }
-
-    public void testClientPrematureDisconnectWithChunkedEncoding() throws IOException {
-        testClientPrematureDisconnect(TransferKind.CHUNKED);
-    }
-
-    public void testClientPrematureDisconnectWithNoLengthHeaders() throws IOException {
-        testClientPrematureDisconnect(TransferKind.END_OF_STREAM);
-    }
-
-    private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException {
-        MockResponse response = new MockResponse();
-        transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 1024);
-        server.enqueue(response);
-        server.enqueue(new MockResponse().setBody("Request #2"));
-        server.play();
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        InputStream in = connection.getInputStream();
-        assertEquals("ABCDE", readAscii(connection, 5));
-        in.close();
-        try {
-            in.read();
-            fail("Expected an IOException because the stream is closed.");
-        } catch (IOException expected) {
-        }
-
-        assertEquals(1, cache.getWriteAbortCount());
-        assertEquals(0, cache.getWriteSuccessCount());
-        connection = server.getUrl("/").openConnection();
-        assertEquals("Request #2", readAscii(connection));
-        assertEquals(1, cache.getWriteAbortCount());
-        assertEquals(1, cache.getWriteSuccessCount());
-    }
-
-    public void testDefaultExpirationDateFullyCachedForLessThan24Hours() throws Exception {
-        //      last modified: 105 seconds ago
-        //             served:   5 seconds ago
-        //   default lifetime: (105 - 5) / 10 = 10 seconds
-        //            expires:  10 seconds from served date = 5 seconds from now
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS))
-                .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS))
-                .setBody("A"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        URLConnection connection = url.openConnection();
-        assertEquals("A", readAscii(connection));
-        assertNull(connection.getHeaderField("Warning"));
-    }
-
-    public void testDefaultExpirationDateConditionallyCached() throws Exception {
-        //      last modified: 115 seconds ago
-        //             served:  15 seconds ago
-        //   default lifetime: (115 - 15) / 10 = 10 seconds
-        //            expires:  10 seconds from served date = 5 seconds ago
-        String lastModifiedDate = formatDate(-115, TimeUnit.SECONDS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Date: " + formatDate(-15, TimeUnit.SECONDS)));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testDefaultExpirationDateFullyCachedForMoreThan24Hours() throws Exception {
-        //      last modified: 105 days ago
-        //             served:   5 days ago
-        //   default lifetime: (105 - 5) / 10 = 10 days
-        //            expires:  10 days from served date = 5 days from now
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.DAYS))
-                .addHeader("Date: " + formatDate(-5, TimeUnit.DAYS))
-                .setBody("A"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        URLConnection connection = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection));
-        assertEquals("113 HttpURLConnection \"Heuristic expiration\"",
-                connection.getHeaderField("Warning"));
-    }
-
-    public void testNoDefaultExpirationForUrlsWithQueryString() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS))
-                .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS))
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/?foo=bar");
-        assertEquals("A", readAscii(url.openConnection()));
-        assertEquals("B", readAscii(url.openConnection()));
-    }
-
-    public void testExpirationDateInThePastWithLastModifiedHeader() throws Exception {
-        String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testExpirationDateInThePastWithNoLastModifiedHeader() throws Exception {
-        assertNotCached(new MockResponse()
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
-    }
-
-    public void testExpirationDateInTheFuture() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
-    }
-
-    public void testMaxAgePreferredWithMaxAgeAndExpires() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Date: " + formatDate(0, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgeInThePastWithDateAndLastModifiedHeaders() throws Exception {
-        String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Cache-Control: max-age=60"));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testMaxAgeInThePastWithDateHeaderButNoLastModifiedHeader() throws Exception {
-        /*
-         * Chrome interprets max-age relative to the local clock. Both our cache
-         * and Firefox both use the earlier of the local and server's clock.
-         */
-        assertNotCached(new MockResponse()
-                .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgeInTheFutureWithDateHeader() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Date: " + formatDate(0, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgeInTheFutureWithNoDateHeader() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgeWithLastModifiedButNoServedDate() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgeInTheFutureWithDateAndLastModifiedHeaders() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testMaxAgePreferredOverLowerSharedMaxAge() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES))
-                .addHeader("Cache-Control: s-maxage=60")
-                .addHeader("Cache-Control: max-age=180"));
-    }
-
-    public void testMaxAgePreferredOverHigherMaxAge() throws Exception {
-        assertNotCached(new MockResponse()
-                .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES))
-                .addHeader("Cache-Control: s-maxage=180")
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testRequestMethodOptionsIsNotCached() throws Exception {
-        testRequestMethod("OPTIONS", false);
-    }
-
-    public void testRequestMethodGetIsCached() throws Exception {
-        testRequestMethod("GET", true);
-    }
-
-    public void testRequestMethodHeadIsNotCached() throws Exception {
-        // We could support this but choose not to for implementation simplicity
-        testRequestMethod("HEAD", false);
-    }
-
-    public void testRequestMethodPostIsNotCached() throws Exception {
-        // We could support this but choose not to for implementation simplicity
-        testRequestMethod("POST", false);
-    }
-
-    public void testRequestMethodPutIsNotCached() throws Exception {
-        testRequestMethod("PUT", false);
-    }
-
-    public void testRequestMethodDeleteIsNotCached() throws Exception {
-        testRequestMethod("DELETE", false);
-    }
-
-    public void testRequestMethodTraceIsNotCached() throws Exception {
-        testRequestMethod("TRACE", false);
-    }
-
-    private void testRequestMethod(String requestMethod, boolean expectCached) throws Exception {
-        /*
-         * 1. seed the cache (potentially)
-         * 2. expect a cache hit or miss
-         */
-        server.enqueue(new MockResponse()
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .addHeader("X-Response-ID: 1"));
-        server.enqueue(new MockResponse()
-                .addHeader("X-Response-ID: 2"));
-        server.play();
-
-        URL url = server.getUrl("/");
-
-        HttpURLConnection request1 = (HttpURLConnection) url.openConnection();
-        request1.setRequestMethod(requestMethod);
-        addRequestBodyIfNecessary(requestMethod, request1);
-        assertEquals("1", request1.getHeaderField("X-Response-ID"));
-
-        URLConnection request2 = url.openConnection();
-        if (expectCached) {
-            assertEquals("1", request1.getHeaderField("X-Response-ID"));
-        } else {
-            assertEquals("2", request2.getHeaderField("X-Response-ID"));
-        }
-    }
-
-    public void testPostInvalidatesCache() throws Exception {
-        testMethodInvalidates("POST");
-    }
-
-    public void testPutInvalidatesCache() throws Exception {
-        testMethodInvalidates("PUT");
-    }
-
-    public void testDeleteMethodInvalidatesCache() throws Exception {
-        testMethodInvalidates("DELETE");
-    }
-
-    private void testMethodInvalidates(String requestMethod) throws Exception {
-        /*
-         * 1. seed the cache
-         * 2. invalidate it
-         * 3. expect a cache miss
-         */
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.enqueue(new MockResponse().setBody("C"));
-        server.play();
-
-        URL url = server.getUrl("/");
-
-        assertEquals("A", readAscii(url.openConnection()));
-
-        HttpURLConnection invalidate = (HttpURLConnection) url.openConnection();
-        invalidate.setRequestMethod(requestMethod);
-        addRequestBodyIfNecessary(requestMethod, invalidate);
-        assertEquals("B", readAscii(invalidate));
-
-        assertEquals("C", readAscii(url.openConnection()));
-    }
-
-    public void testEtag() throws Exception {
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("ETag: v1"));
-        assertTrue(conditionalRequest.getHeaders().contains("If-None-Match: v1"));
-    }
-
-    public void testEtagAndExpirationDateInThePast() throws Exception {
-        String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("ETag: v1")
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-None-Match: v1"));
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testEtagAndExpirationDateInTheFuture() throws Exception {
-        assertFullyCached(new MockResponse()
-                .addHeader("ETag: v1")
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
-    }
-
-    public void testCacheControlNoCache() throws Exception {
-        assertNotCached(new MockResponse().addHeader("Cache-Control: no-cache"));
-    }
-
-    public void testCacheControlNoCacheAndExpirationDateInTheFuture() throws Exception {
-        String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: no-cache"));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testPragmaNoCache() throws Exception {
-        assertNotCached(new MockResponse().addHeader("Pragma: no-cache"));
-    }
-
-    public void testPragmaNoCacheAndExpirationDateInTheFuture() throws Exception {
-        String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
-        RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .addHeader("Pragma: no-cache"));
-        List<String> headers = conditionalRequest.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    public void testCacheControlNoStore() throws Exception {
-        assertNotCached(new MockResponse().addHeader("Cache-Control: no-store"));
-    }
-
-    public void testCacheControlNoStoreAndExpirationDateInTheFuture() throws Exception {
-        assertNotCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: no-store"));
-    }
-
-    public void testPartialRangeResponsesDoNotCorruptCache() throws Exception {
-        /*
-         * 1. request a range
-         * 2. request a full document, expecting a cache miss
-         */
-        server.enqueue(new MockResponse().setBody("AA")
-                .setResponseCode(HttpURLConnection.HTTP_PARTIAL)
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
-                .addHeader("Content-Range: bytes 1000-1001/2000"));
-        server.enqueue(new MockResponse().setBody("BB"));
-        server.play();
-
-        URL url = server.getUrl("/");
-
-        URLConnection range = url.openConnection();
-        range.addRequestProperty("Range", "bytes=1000-1001");
-        assertEquals("AA", readAscii(range));
-
-        assertEquals("BB", readAscii(url.openConnection()));
-    }
-
-    public void testServerReturnsDocumentOlderThanCache() throws Exception {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
-        server.enqueue(new MockResponse().setBody("B")
-                .addHeader("Last-Modified: " + formatDate(-4, TimeUnit.HOURS)));
-        server.play();
-
-        URL url = server.getUrl("/");
-
-        assertEquals("A", readAscii(url.openConnection()));
-        assertEquals("A", readAscii(url.openConnection()));
-    }
-
-    public void testNonIdentityEncodingAndConditionalCache() throws Exception {
-        assertNonIdentityEncodingCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
-    }
-
-    public void testNonIdentityEncodingAndFullCache() throws Exception {
-        assertNonIdentityEncodingCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
-    }
-
-    private void assertNonIdentityEncodingCached(MockResponse response) throws Exception {
-        server.enqueue(response
-                .setBody(gzip("ABCABCABC".getBytes("UTF-8")))
-                .addHeader("Content-Encoding: gzip"));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-
-        server.play();
-        assertEquals("ABCABCABC", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("ABCABCABC", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testExpiresDateBeforeModifiedDate() throws Exception {
-        assertConditionallyCached(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Expires: " + formatDate(-2, TimeUnit.HOURS)));
-    }
-
-    public void testRequestMaxAge() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
-                .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES))
-                .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
-        server.enqueue(new MockResponse().setBody("B"));
-
-        server.play();
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "max-age=30");
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testRequestMinFresh() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES)));
-        server.enqueue(new MockResponse().setBody("B"));
-
-        server.play();
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "min-fresh=120");
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testRequestMaxStale() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Cache-Control: max-age=120")
-                .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES)));
-        server.enqueue(new MockResponse().setBody("B"));
-
-        server.play();
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "max-stale=180");
-        assertEquals("A", readAscii(connection));
-        assertEquals("110 HttpURLConnection \"Response is stale\"",
-                connection.getHeaderField("Warning"));
-    }
-
-    public void testRequestMaxStaleNotHonoredWithMustRevalidate() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Cache-Control: max-age=120, must-revalidate")
-                .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES)));
-        server.enqueue(new MockResponse().setBody("B"));
-
-        server.play();
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "max-stale=180");
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testRequestOnlyIfCachedWithNoResponseCached() throws IOException {
-        // (no responses enqueued)
-        server.play();
-
-        HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "only-if-cached");
-        assertGatewayTimeout(connection);
-    }
-
-    public void testRequestOnlyIfCachedWithFullResponseCached() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Cache-Control: max-age=30")
-                .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES)));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "only-if-cached");
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testRequestOnlyIfCachedWithConditionalResponseCached() throws IOException {
-        server.enqueue(new MockResponse().setBody("A")
-                .addHeader("Cache-Control: max-age=30")
-                .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES)));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "only-if-cached");
-        assertGatewayTimeout(connection);
-    }
-
-    public void testRequestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException {
-        server.enqueue(new MockResponse().setBody("A"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        connection.addRequestProperty("Cache-Control", "only-if-cached");
-        assertGatewayTimeout(connection);
-    }
-
-    public void testRequestCacheControlNoCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        URLConnection connection = url.openConnection();
-        connection.setRequestProperty("Cache-Control", "no-cache");
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testRequestPragmaNoCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
-                .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        URLConnection connection = url.openConnection();
-        connection.setRequestProperty("Pragma", "no-cache");
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testClientSuppliedIfModifiedSinceWithCachedResult() throws Exception {
-        MockResponse response = new MockResponse()
-                .addHeader("ETag: v3")
-                .addHeader("Cache-Control: max-age=0");
-        String ifModifiedSinceDate = formatDate(-24, TimeUnit.HOURS);
-        RecordedRequest request = assertClientSuppliedCondition(
-                response, "If-Modified-Since", ifModifiedSinceDate);
-        List<String> headers = request.getHeaders();
-        assertTrue(headers.contains("If-Modified-Since: " + ifModifiedSinceDate));
-        assertFalse(headers.contains("If-None-Match: v3"));
-    }
-
-    public void testClientSuppliedIfNoneMatchSinceWithCachedResult() throws Exception {
-        String lastModifiedDate = formatDate(-3, TimeUnit.MINUTES);
-        MockResponse response = new MockResponse()
-                .addHeader("Last-Modified: " + lastModifiedDate)
-                .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES))
-                .addHeader("Cache-Control: max-age=0");
-        RecordedRequest request = assertClientSuppliedCondition(
-                response, "If-None-Match", "v1");
-        List<String> headers = request.getHeaders();
-        assertTrue(headers.contains("If-None-Match: v1"));
-        assertFalse(headers.contains("If-Modified-Since: " + lastModifiedDate));
-    }
-
-    private RecordedRequest assertClientSuppliedCondition(MockResponse seed, String conditionName,
-            String conditionValue) throws Exception {
-        server.enqueue(seed.setBody("A"));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-
-        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
-        connection.addRequestProperty(conditionName, conditionValue);
-        assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode());
-        assertEquals("", readAscii(connection));
-
-        server.takeRequest(); // seed
-        return server.takeRequest();
-    }
-
-    public void testSetIfModifiedSince() throws Exception {
-        Date since = new Date();
-        server.enqueue(new MockResponse().setBody("A"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection = url.openConnection();
-        connection.setIfModifiedSince(since.getTime());
-        assertEquals("A", readAscii(connection));
-        RecordedRequest request = server.takeRequest();
-        assertTrue(request.getHeaders().contains("If-Modified-Since: " + formatDate(since)));
-    }
-
-    public void testClientSuppliedConditionWithoutCachedResult() throws Exception {
-        server.enqueue(new MockResponse()
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
-        String clientIfModifiedSince = formatDate(-24, TimeUnit.HOURS);
-        connection.addRequestProperty("If-Modified-Since", clientIfModifiedSince);
-        assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode());
-        assertEquals("", readAscii(connection));
-    }
-
-    public void testAuthorizationRequestHeaderPreventsCaching() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.MINUTES))
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection = url.openConnection();
-        connection.addRequestProperty("Authorization", "password");
-        assertEquals("A", readAscii(connection));
-        assertEquals("B", readAscii(url.openConnection()));
-    }
-
-    public void testAuthorizationResponseCachedWithSMaxAge() throws Exception {
-        assertAuthorizationRequestFullyCached(new MockResponse()
-                .addHeader("Cache-Control: s-maxage=60"));
-    }
-
-    public void testAuthorizationResponseCachedWithPublic() throws Exception {
-        assertAuthorizationRequestFullyCached(new MockResponse()
-                .addHeader("Cache-Control: public"));
-    }
-
-    public void testAuthorizationResponseCachedWithMustRevalidate() throws Exception {
-        assertAuthorizationRequestFullyCached(new MockResponse()
-                .addHeader("Cache-Control: must-revalidate"));
-    }
-
-    public void assertAuthorizationRequestFullyCached(MockResponse response) throws Exception {
-        server.enqueue(response
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection = url.openConnection();
-        connection.addRequestProperty("Authorization", "password");
-        assertEquals("A", readAscii(connection));
-        assertEquals("A", readAscii(url.openConnection()));
-    }
-
-    public void testContentLocationDoesNotPopulateCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Content-Location: /bar")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/foo").openConnection()));
-        assertEquals("B", readAscii(server.getUrl("/bar").openConnection()));
-    }
-
-    public void testUseCachesFalseDoesNotWriteToCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A").setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.setUseCaches(false);
-        assertEquals("A", readAscii(connection));
-        assertEquals("B", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testUseCachesFalseDoesNotReadFromCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A").setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        URLConnection connection = server.getUrl("/").openConnection();
-        connection.setUseCaches(false);
-        assertEquals("B", readAscii(connection));
-    }
-
-    public void testDefaultUseCachesSetsInitialValueOnly() throws Exception {
-        URL url = new URL("http://localhost/");
-        URLConnection c1 = url.openConnection();
-        URLConnection c2 = url.openConnection();
-        assertTrue(c1.getDefaultUseCaches());
-        c1.setDefaultUseCaches(false);
-        try {
-            assertTrue(c1.getUseCaches());
-            assertTrue(c2.getUseCaches());
-            URLConnection c3 = url.openConnection();
-            assertFalse(c3.getUseCaches());
-        } finally {
-            c1.setDefaultUseCaches(true);
-        }
-    }
-
-    public void testConnectionIsReturnedToPoolAfterConditionalSuccess() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/a").openConnection()));
-        assertEquals("A", readAscii(server.getUrl("/a").openConnection()));
-        assertEquals("B", readAscii(server.getUrl("/b").openConnection()));
-
-        assertEquals(0, server.takeRequest().getSequenceNumber());
-        assertEquals(1, server.takeRequest().getSequenceNumber());
-        assertEquals(2, server.takeRequest().getSequenceNumber());
-    }
-
-    public void testStatisticsConditionalCacheMiss() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.enqueue(new MockResponse().setBody("C"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(1, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(0, cache.getHitCount());
-        assertEquals("B", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("C", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(3, cache.getRequestCount());
-        assertEquals(3, cache.getNetworkCount());
-        assertEquals(0, cache.getHitCount());
-    }
-
-    public void testStatisticsConditionalCacheHit() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(1, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(0, cache.getHitCount());
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(3, cache.getRequestCount());
-        assertEquals(3, cache.getNetworkCount());
-        assertEquals(2, cache.getHitCount());
-    }
-
-    public void testStatisticsFullCacheHit() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(1, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(0, cache.getHitCount());
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals(3, cache.getRequestCount());
-        assertEquals(1, cache.getNetworkCount());
-        assertEquals(2, cache.getHitCount());
-    }
-
-    public void testVaryMatchesChangedRequestHeaderField() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        HttpURLConnection frConnection = (HttpURLConnection) url.openConnection();
-        frConnection.addRequestProperty("Accept-Language", "fr-CA");
-        assertEquals("A", readAscii(frConnection));
-
-        HttpURLConnection enConnection = (HttpURLConnection) url.openConnection();
-        enConnection.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("B", readAscii(enConnection));
-    }
-
-    public void testVaryMatchesUnchangedRequestHeaderField() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection1 = url.openConnection();
-        connection1.addRequestProperty("Accept-Language", "fr-CA");
-        assertEquals("A", readAscii(connection1));
-        URLConnection connection2 = url.openConnection();
-        connection2.addRequestProperty("Accept-Language", "fr-CA");
-        assertEquals("A", readAscii(connection2));
-    }
-
-    public void testVaryMatchesAbsentRequestHeaderField() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Foo")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testVaryMatchesAddedRequestHeaderField() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Foo")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        URLConnection fooConnection = server.getUrl("/").openConnection();
-        fooConnection.addRequestProperty("Foo", "bar");
-        assertEquals("B", readAscii(fooConnection));
-    }
-
-    public void testVaryMatchesRemovedRequestHeaderField() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Foo")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URLConnection fooConnection = server.getUrl("/").openConnection();
-        fooConnection.addRequestProperty("Foo", "bar");
-        assertEquals("A", readAscii(fooConnection));
-        assertEquals("B", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testVaryFieldsAreCaseInsensitive() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: ACCEPT-LANGUAGE")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection1 = url.openConnection();
-        connection1.addRequestProperty("Accept-Language", "fr-CA");
-        assertEquals("A", readAscii(connection1));
-        URLConnection connection2 = url.openConnection();
-        connection2.addRequestProperty("accept-language", "fr-CA");
-        assertEquals("A", readAscii(connection2));
-    }
-
-    public void testVaryMultipleFieldsWithMatch() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language, Accept-Charset")
-                .addHeader("Vary: Accept-Encoding")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection1 = url.openConnection();
-        connection1.addRequestProperty("Accept-Language", "fr-CA");
-        connection1.addRequestProperty("Accept-Charset", "UTF-8");
-        connection1.addRequestProperty("Accept-Encoding", "identity");
-        assertEquals("A", readAscii(connection1));
-        URLConnection connection2 = url.openConnection();
-        connection2.addRequestProperty("Accept-Language", "fr-CA");
-        connection2.addRequestProperty("Accept-Charset", "UTF-8");
-        connection2.addRequestProperty("Accept-Encoding", "identity");
-        assertEquals("A", readAscii(connection2));
-    }
-
-    public void testVaryMultipleFieldsWithNoMatch() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language, Accept-Charset")
-                .addHeader("Vary: Accept-Encoding")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection frConnection = url.openConnection();
-        frConnection.addRequestProperty("Accept-Language", "fr-CA");
-        frConnection.addRequestProperty("Accept-Charset", "UTF-8");
-        frConnection.addRequestProperty("Accept-Encoding", "identity");
-        assertEquals("A", readAscii(frConnection));
-        URLConnection enConnection = url.openConnection();
-        enConnection.addRequestProperty("Accept-Language", "en-CA");
-        enConnection.addRequestProperty("Accept-Charset", "UTF-8");
-        enConnection.addRequestProperty("Accept-Encoding", "identity");
-        assertEquals("B", readAscii(enConnection));
-    }
-
-    public void testVaryMultipleFieldValuesWithMatch() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection1 = url.openConnection();
-        connection1.addRequestProperty("Accept-Language", "fr-CA, fr-FR");
-        connection1.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("A", readAscii(connection1));
-
-        URLConnection connection2 = url.openConnection();
-        connection2.addRequestProperty("Accept-Language", "fr-CA, fr-FR");
-        connection2.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("A", readAscii(connection2));
-    }
-
-    public void testVaryMultipleFieldValuesWithNoMatch() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        URLConnection connection1 = url.openConnection();
-        connection1.addRequestProperty("Accept-Language", "fr-CA, fr-FR");
-        connection1.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("A", readAscii(connection1));
-
-        URLConnection connection2 = url.openConnection();
-        connection2.addRequestProperty("Accept-Language", "fr-CA");
-        connection2.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("B", readAscii(connection2));
-    }
-
-    public void testVaryAsterisk() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: *")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-        assertEquals("B", readAscii(server.getUrl("/").openConnection()));
-    }
-
-    public void testVaryAndHttps() throws Exception {
-        TestSSLContext testSSLContext = TestSSLContext.create();
-        server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .addHeader("Vary: Accept-Language")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        HttpsURLConnection connection1 = (HttpsURLConnection) url.openConnection();
-        connection1.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        connection1.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("A", readAscii(connection1));
-
-        HttpsURLConnection connection2 = (HttpsURLConnection) url.openConnection();
-        connection2.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-        connection2.addRequestProperty("Accept-Language", "en-US");
-        assertEquals("A", readAscii(connection2));
-    }
-
-    public void testDiskWriteFailureCacheDegradation() throws Exception {
-        Deque<InvocationHandler> writeHandlers = mockOs.getHandlers("write");
-        int i = 0;
-        boolean hasMoreScenarios = true;
-        while (hasMoreScenarios) {
-            mockOs.enqueueNormal("write", i++);
-            mockOs.enqueueFault("write");
-            exercisePossiblyFaultyCache(false);
-            hasMoreScenarios = writeHandlers.isEmpty();
-            writeHandlers.clear();
-        }
-        System.out.println("Exercising the cache performs " + (i - 1) + " writes.");
-    }
-
-    public void testDiskReadFailureCacheDegradation() throws Exception {
-        Deque<InvocationHandler> readHandlers = mockOs.getHandlers("read");
-        int i = 0;
-        boolean hasMoreScenarios = true;
-        while (hasMoreScenarios) {
-            mockOs.enqueueNormal("read", i++);
-            mockOs.enqueueFault("read");
-            exercisePossiblyFaultyCache(true);
-            hasMoreScenarios = readHandlers.isEmpty();
-            readHandlers.clear();
-        }
-        System.out.println("Exercising the cache performs " + (i - 1) + " reads.");
-    }
-
-    public void testCachePlusCookies() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Set-Cookie: a=FIRST; domain=" + server.getCookieDomain() + ";")
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .addHeader("Set-Cookie: a=SECOND; domain=" + server.getCookieDomain() + ";")
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        assertCookies(url, "a=FIRST");
-        assertEquals("A", readAscii(url.openConnection()));
-        assertCookies(url, "a=SECOND");
-    }
-
-    public void testGetHeadersReturnsNetworkEndToEndHeaders() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Allow: GET, HEAD")
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .addHeader("Allow: GET, HEAD, PUT")
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URLConnection connection1 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals("GET, HEAD", connection1.getHeaderField("Allow"));
-
-        URLConnection connection2 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection2));
-        assertEquals("GET, HEAD, PUT", connection2.getHeaderField("Allow"));
-    }
-
-    public void testGetHeadersReturnsCachedHopByHopHeaders() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Transfer-Encoding: identity")
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .addHeader("Transfer-Encoding: none")
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URLConnection connection1 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals("identity", connection1.getHeaderField("Transfer-Encoding"));
-
-        URLConnection connection2 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection2));
-        assertEquals("identity", connection2.getHeaderField("Transfer-Encoding"));
-    }
-
-    public void testGetHeadersDeletesCached100LevelWarnings() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Warning: 199 test danger")
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URLConnection connection1 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals("199 test danger", connection1.getHeaderField("Warning"));
-
-        URLConnection connection2 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection2));
-        assertEquals(null, connection2.getHeaderField("Warning"));
-    }
-
-    public void testGetHeadersRetainsCached200LevelWarnings() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Warning: 299 test danger")
-                .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.play();
-
-        URLConnection connection1 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals("299 test danger", connection1.getHeaderField("Warning"));
-
-        URLConnection connection2 = server.getUrl("/").openConnection();
-        assertEquals("A", readAscii(connection2));
-        assertEquals("299 test danger", connection2.getHeaderField("Warning"));
-    }
-
-    public void assertCookies(URL url, String... expectedCookies) throws Exception {
-        List<String> actualCookies = new ArrayList<String>();
-        for (HttpCookie cookie : cookieManager.getCookieStore().get(url.toURI())) {
-            actualCookies.add(cookie.toString());
-        }
-        assertEquals(Arrays.asList(expectedCookies), actualCookies);
-    }
-
-    public void testCachePlusRange() throws Exception {
-        assertNotCached(new MockResponse()
-                .setResponseCode(HttpURLConnection.HTTP_PARTIAL)
-                .addHeader("Date: " + formatDate(0, TimeUnit.HOURS))
-                .addHeader("Content-Range: bytes 100-100/200")
-                .addHeader("Cache-Control: max-age=60"));
-    }
-
-    public void testConditionalHitUpdatesCache() throws Exception {
-        server.enqueue(new MockResponse()
-                .addHeader("Last-Modified: " + formatDate(0, TimeUnit.SECONDS))
-                .addHeader("Cache-Control: max-age=0")
-                .setBody("A"));
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=30")
-                .addHeader("Allow: GET, HEAD")
-                .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        // cache miss; seed the cache
-        HttpURLConnection connection1 = (HttpURLConnection) server.getUrl("/a").openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals(null, connection1.getHeaderField("Allow"));
-
-        // conditional cache hit; update the cache
-        HttpURLConnection connection2 = (HttpURLConnection) server.getUrl("/a").openConnection();
-        assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode());
-        assertEquals("A", readAscii(connection2));
-        assertEquals("GET, HEAD", connection2.getHeaderField("Allow"));
-
-        // full cache hit
-        HttpURLConnection connection3 = (HttpURLConnection) server.getUrl("/a").openConnection();
-        assertEquals("A", readAscii(connection3));
-        assertEquals("GET, HEAD", connection3.getHeaderField("Allow"));
-
-        assertEquals(2, server.getRequestCount());
-    }
-
-    /**
-     * @param delta the offset from the current date to use. Negative
-     *     values yield dates in the past; positive values yield dates in the
-     *     future.
-     */
-    private String formatDate(long delta, TimeUnit timeUnit) {
-        return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta)));
-    }
-
-    private String formatDate(Date date) {
-        DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
-        rfc1123.setTimeZone(TimeZone.getTimeZone("UTC"));
-        return rfc1123.format(date);
-    }
-
-    private void addRequestBodyIfNecessary(String requestMethod, HttpURLConnection invalidate)
-            throws IOException {
-        if (requestMethod.equals("POST") || requestMethod.equals("PUT")) {
-            invalidate.setDoOutput(true);
-            OutputStream requestBody = invalidate.getOutputStream();
-            requestBody.write('x');
-            requestBody.close();
-        }
-    }
-
-    private void assertNotCached(MockResponse response) throws Exception {
-        server.enqueue(response.setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        assertEquals("B", readAscii(url.openConnection()));
-    }
-
-    private void exercisePossiblyFaultyCache(boolean permitReadBodyFailures) throws Exception {
-        server.shutdown();
-        server = new MockWebServer();
-        server.enqueue(new MockResponse()
-                .addHeader("Cache-Control: max-age=60")
-                .setBody("A"));
-        server.enqueue(new MockResponse().setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/" + UUID.randomUUID());
-        assertEquals("A", readAscii(url.openConnection()));
-
-        URLConnection connection = url.openConnection();
-        InputStream in = connection.getInputStream();
-        try {
-            int bodyChar = in.read();
-            assertTrue(bodyChar == 'A' || bodyChar == 'B');
-            assertEquals(-1, in.read());
-        } catch (IOException e) {
-            if (!permitReadBodyFailures) {
-                throw e;
-            }
-        }
-    }
-
-    /**
-     * @return the request with the conditional get headers.
-     */
-    private RecordedRequest assertConditionallyCached(MockResponse response) throws Exception {
-        // scenario 1: condition succeeds
-        server.enqueue(response.setBody("A").setStatus("HTTP/1.1 200 A-OK"));
-        server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-
-        // scenario 2: condition fails
-        server.enqueue(response.setBody("B").setStatus("HTTP/1.1 200 B-OK"));
-        server.enqueue(new MockResponse().setStatus("HTTP/1.1 200 C-OK").setBody("C"));
-
-        server.play();
-
-        URL valid = server.getUrl("/valid");
-        HttpURLConnection connection1 = (HttpURLConnection) valid.openConnection();
-        assertEquals("A", readAscii(connection1));
-        assertEquals(HttpURLConnection.HTTP_OK, connection1.getResponseCode());
-        assertEquals("A-OK", connection1.getResponseMessage());
-        HttpURLConnection connection2 = (HttpURLConnection) valid.openConnection();
-        assertEquals("A", readAscii(connection2));
-        assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode());
-        assertEquals("A-OK", connection2.getResponseMessage());
-
-        URL invalid = server.getUrl("/invalid");
-        HttpURLConnection connection3 = (HttpURLConnection) invalid.openConnection();
-        assertEquals("B", readAscii(connection3));
-        assertEquals(HttpURLConnection.HTTP_OK, connection3.getResponseCode());
-        assertEquals("B-OK", connection3.getResponseMessage());
-        HttpURLConnection connection4 = (HttpURLConnection) invalid.openConnection();
-        assertEquals("C", readAscii(connection4));
-        assertEquals(HttpURLConnection.HTTP_OK, connection4.getResponseCode());
-        assertEquals("C-OK", connection4.getResponseMessage());
-
-        server.takeRequest(); // regular get
-        return server.takeRequest(); // conditional get
-    }
-
-    private void assertFullyCached(MockResponse response) throws Exception {
-        server.enqueue(response.setBody("A"));
-        server.enqueue(response.setBody("B"));
-        server.play();
-
-        URL url = server.getUrl("/");
-        assertEquals("A", readAscii(url.openConnection()));
-        assertEquals("A", readAscii(url.openConnection()));
-    }
-
-    /**
-     * Shortens the body of {@code response} but not the corresponding headers.
-     * Only useful to test how clients respond to the premature conclusion of
-     * the HTTP body.
-     */
-    private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) {
-        response.setSocketPolicy(DISCONNECT_AT_END);
-        List<String> headers = new ArrayList<String>(response.getHeaders());
-        response.setBody(Arrays.copyOfRange(response.getBody(), 0, numBytesToKeep));
-        response.getHeaders().clear();
-        response.getHeaders().addAll(headers);
-        return response;
-    }
-
-    /**
-     * Reads {@code count} characters from the stream. If the stream is
-     * exhausted before {@code count} characters can be read, the remaining
-     * characters are returned and the stream is closed.
-     */
-    private String readAscii(URLConnection connection, int count) throws IOException {
-        HttpURLConnection httpConnection = (HttpURLConnection) connection;
-        InputStream in = httpConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST
-                ? connection.getInputStream()
-                : httpConnection.getErrorStream();
-        StringBuilder result = new StringBuilder();
-        for (int i = 0; i < count; i++) {
-            int value = in.read();
-            if (value == -1) {
-                in.close();
-                break;
-            }
-            result.append((char) value);
-        }
-        return result.toString();
-    }
-
-    private String readAscii(URLConnection connection) throws IOException {
-        return readAscii(connection, Integer.MAX_VALUE);
-    }
-
-    private void reliableSkip(InputStream in, int length) throws IOException {
-        while (length > 0) {
-            length -= in.skip(length);
-        }
-    }
-
-    private void assertGatewayTimeout(HttpURLConnection connection) throws IOException {
-        try {
-            connection.getInputStream();
-            fail();
-        } catch (FileNotFoundException expected) {
-        }
-        assertEquals(504, connection.getResponseCode());
-        assertEquals(-1, connection.getErrorStream().read());
-    }
-
-    enum TransferKind {
-        CHUNKED() {
-            @Override void setBody(MockResponse response, byte[] content, int chunkSize)
-                    throws IOException {
-                response.setChunkedBody(content, chunkSize);
-            }
-        },
-        FIXED_LENGTH() {
-            @Override void setBody(MockResponse response, byte[] content, int chunkSize) {
-                response.setBody(content);
-            }
-        },
-        END_OF_STREAM() {
-            @Override void setBody(MockResponse response, byte[] content, int chunkSize) {
-                response.setBody(content);
-                response.setSocketPolicy(DISCONNECT_AT_END);
-                for (Iterator<String> h = response.getHeaders().iterator(); h.hasNext(); ) {
-                    if (h.next().startsWith("Content-Length:")) {
-                        h.remove();
-                        break;
-                    }
-                }
-            }
-        };
-
-        abstract void setBody(MockResponse response, byte[] content, int chunkSize)
-                throws IOException;
-
-        void setBody(MockResponse response, String content, int chunkSize) throws IOException {
-            setBody(response, content.getBytes("UTF-8"), chunkSize);
-        }
-    }
-
-    private <T> List<T> toListOrNull(T[] arrayOrNull) {
-        return arrayOrNull != null ? Arrays.asList(arrayOrNull) : null;
-    }
-
-    /**
-     * Returns a gzipped copy of {@code bytes}.
-     */
-    public byte[] gzip(byte[] bytes) throws IOException {
-        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
-        OutputStream gzippedOut = new GZIPOutputStream(bytesOut);
-        gzippedOut.write(bytes);
-        gzippedOut.close();
-        return bytesOut.toByteArray();
-    }
-
-    private class InsecureResponseCache extends ResponseCache {
-        @Override public CacheRequest put(URI uri, URLConnection connection) throws IOException {
-            return cache.put(uri, connection);
-        }
-
-        @Override public CacheResponse get(URI uri, String requestMethod,
-                Map<String, List<String>> requestHeaders) throws IOException {
-            final CacheResponse response = cache.get(uri, requestMethod, requestHeaders);
-            if (response instanceof SecureCacheResponse) {
-                return new CacheResponse() {
-                    @Override public InputStream getBody() throws IOException {
-                        return response.getBody();
-                    }
-                    @Override public Map<String, List<String>> getHeaders() throws IOException {
-                        return response.getHeaders();
-                    }
-                };
-            }
-            return response;
-        }
-    }
-}
diff --git a/luni/src/test/java/libcore/net/http/ParsedHeadersTest.java b/luni/src/test/java/libcore/net/http/ParsedHeadersTest.java
deleted file mode 100644
index d7ba441..0000000
--- a/luni/src/test/java/libcore/net/http/ParsedHeadersTest.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-* Copyright (C) 2011 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-package libcore.net.http;
-
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import junit.framework.TestCase;
-
-public final class ParsedHeadersTest extends TestCase {
-
-    private URI uri;
-
-    @Override protected void setUp() throws Exception {
-        super.setUp();
-        uri = new URI("http", "localhost", "/");
-    }
-
-    public void testUpperCaseHttpHeaders() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("CACHE-CONTROL", "no-store");
-        headers.add("DATE", "Thu, 01 Jan 1970 00:00:01 UTC");
-        headers.add("EXPIRES", "Thu, 01 Jan 1970 00:00:02 UTC");
-        headers.add("LAST-MODIFIED", "Thu, 01 Jan 1970 00:00:03 UTC");
-        headers.add("ETAG", "v1");
-        headers.add("PRAGMA", "no-cache");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoStore());
-        assertEquals(new Date(1000), parsedHeaders.getServedDate());
-        assertEquals(new Date(2000), parsedHeaders.getExpires());
-        assertEquals(new Date(3000), parsedHeaders.getLastModified());
-        assertEquals("v1", parsedHeaders.getEtag());
-        assertTrue(parsedHeaders.isNoCache());
-    }
-
-    public void testCommaSeparatedCacheControlHeaders() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "no-store, max-age=60, public");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoStore());
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-        assertTrue(parsedHeaders.isPublic());
-    }
-
-    public void testQuotedFieldName() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "private=\"Set-Cookie\", no-store");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoStore());
-    }
-
-    public void testUnquotedValue() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "private=Set-Cookie, no-store");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoStore());
-    }
-
-    public void testQuotedValue() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "private=\" a, no-cache, c \", no-store");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoStore());
-        assertFalse(parsedHeaders.isNoCache());
-    }
-
-    public void testDanglingQuote() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "private=\"a, no-cache, c");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertFalse(parsedHeaders.isNoCache());
-    }
-
-    public void testTrailingComma() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "public,");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isPublic());
-    }
-
-    public void testTrailingEquals() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "private=");
-        new ResponseHeaders(uri, headers);
-    }
-
-    public void testSpaceBeforeEquals() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "max-age =60");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testSpaceAfterEqualsWithQuotes() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "max-age= \"60\"");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testSpaceAfterEqualsWithoutQuotes() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "max-age= 60");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testCacheControlRequestDirectivesAreCaseInsensitive() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "NO-CACHE");
-        headers.add("Cache-Control", "MAX-AGE=60");
-        headers.add("Cache-Control", "MAX-STALE=70");
-        headers.add("Cache-Control", "MIN-FRESH=80");
-        headers.add("Cache-Control", "ONLY-IF-CACHED");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoCache());
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-        assertEquals(70, parsedHeaders.getMaxStaleSeconds());
-        assertEquals(80, parsedHeaders.getMinFreshSeconds());
-        assertTrue(parsedHeaders.isOnlyIfCached());
-    }
-
-    public void testCacheControlResponseDirectivesAreCaseInsensitive() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "NO-CACHE");
-        headers.add("Cache-Control", "NO-STORE");
-        headers.add("Cache-Control", "MAX-AGE=60");
-        headers.add("Cache-Control", "S-MAXAGE=70");
-        headers.add("Cache-Control", "PUBLIC");
-        headers.add("Cache-Control", "MUST-REVALIDATE");
-        ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoCache());
-        assertTrue(parsedHeaders.isNoStore());
-        assertEquals(60, parsedHeaders.getMaxAgeSeconds());
-        assertEquals(70, parsedHeaders.getSMaxAgeSeconds());
-        assertTrue(parsedHeaders.isPublic());
-        assertTrue(parsedHeaders.isMustRevalidate());
-    }
-
-    public void testPragmaDirectivesAreCaseInsensitive() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Pragma", "NO-CACHE");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertTrue(parsedHeaders.isNoCache());
-    }
-
-    public void testMissingInteger() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "max-age");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(-1, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testInvalidInteger() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "MAX-AGE=pi");
-        RequestHeaders requestHeaders = new RequestHeaders(uri, headers);
-        assertEquals(-1, requestHeaders.getMaxAgeSeconds());
-    }
-
-    public void testVeryLargeInteger() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "MAX-AGE=" + (Integer.MAX_VALUE + 1L));
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(Integer.MAX_VALUE, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testNegativeInteger() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("Cache-Control", "MAX-AGE=-2");
-        RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
-        assertEquals(0, parsedHeaders.getMaxAgeSeconds());
-    }
-
-    public void testParseChallengesWithCommaInRealm() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "s1 realm=\"ab,cd\", s2 realm=\"ef,gh\"");
-        assertEquals(Arrays.asList(new Challenge("s1", "ab,cd"), new Challenge("s2", "ef,gh")),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    public void testParseChallengesWithMultipleHeaders() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "s1 realm=\"abc\"");
-        headers.add("WWW-Authenticate", "s2 realm=\"def\"");
-        assertEquals(Arrays.asList(new Challenge("s1", "abc"), new Challenge("s2", "def")),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    public void testParseChallengesWithExtraWhitespace() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "  s1  realm=\"a\"  ,  s2  realm=\"b\",  ");
-        assertEquals(Arrays.asList(new Challenge("s1", "a"), new Challenge("s2", "b")),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    public void testParseChallengesWithMissingRealm() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "Basic");
-        assertEquals(Collections.<Challenge>emptyList(),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    public void testParseChallengesWithEmptyRealm() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "Basic realm=\"\"");
-        assertEquals(Arrays.asList(new Challenge("Basic", "")),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    public void testParseChallengesWithMissingScheme() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "realm=\"a\"");
-        assertEquals(Collections.<Challenge>emptyList(),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-
-    // http://code.google.com/p/android/issues/detail?id=11140
-    public void testParseChallengesWithManyParameters() {
-        RawHeaders headers = new RawHeaders();
-        headers.add("WWW-Authenticate", "Digest realm=\"abc\","
-                + " qop=\"auth,auth-int\","
-                + " nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\","
-                + " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\","
-                + " Basic realm=\"def\"");
-        assertEquals(Arrays.asList(new Challenge("Digest", "abc"), new Challenge("Basic", "def")),
-                HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
-    }
-}
diff --git a/luni/src/test/java/libcore/net/http/RawHeadersTest.java b/luni/src/test/java/libcore/net/http/RawHeadersTest.java
deleted file mode 100644
index d99e851..0000000
--- a/luni/src/test/java/libcore/net/http/RawHeadersTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 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.net.http;
-
-import java.util.Arrays;
-import junit.framework.TestCase;
-
-public class RawHeadersTest extends TestCase {
-    // http://code.google.com/p/android/issues/detail?id=6684
-    public void test_caseInsensitiveButCasePreserving() {
-        RawHeaders h = new RawHeaders();
-        h.add("Content-Type", "text/plain");
-        // Case-insensitive:
-        assertEquals("text/plain", h.get("Content-Type"));
-        assertEquals("text/plain", h.get("Content-type"));
-        assertEquals("text/plain", h.get("content-type"));
-        assertEquals("text/plain", h.get("CONTENT-TYPE"));
-        // ...but case-preserving:
-        assertEquals("Content-Type", h.toMultimap().keySet().toArray()[0]);
-
-        // We differ from the RI in that the Map we return is also case-insensitive.
-        // Our behavior seems more consistent. (And code that works on the RI will work on Android.)
-        assertEquals(Arrays.asList("text/plain"), h.toMultimap().get("Content-Type"));
-        assertEquals(Arrays.asList("text/plain"), h.toMultimap().get("Content-type")); // RI fails this.
-    }
-
-    // The copy constructor used to be broken for headers with multiple values.
-    // http://code.google.com/p/android/issues/detail?id=6722
-    public void test_copyConstructor() {
-        RawHeaders h1 = new RawHeaders();
-        h1.add("key", "value1");
-        h1.add("key", "value2");
-        RawHeaders h2 = RawHeaders.fromMultimap(h1.toMultimap());
-        assertEquals(2, h2.length());
-        assertEquals("key", h2.getFieldName(0));
-        assertEquals("value1", h2.getValue(0));
-        assertEquals("key", h2.getFieldName(1));
-        assertEquals("value2", h2.getValue(1));
-    }
-}
diff --git a/luni/src/test/java/libcore/util/ZoneInfoDBTest.java b/luni/src/test/java/libcore/util/ZoneInfoDBTest.java
new file mode 100644
index 0000000..d5f2b6e
--- /dev/null
+++ b/luni/src/test/java/libcore/util/ZoneInfoDBTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+package libcore.util;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.RandomAccessFile;
+import java.util.TimeZone;
+
+public class ZoneInfoDBTest extends junit.framework.TestCase {
+  private static final String CURRENT_VERSION = ZoneInfoDB.getInstance().getVersion();
+  private static final String DEFAULT_FILE = System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo/tzdata";
+
+  // An empty override file should fall back to the default file.
+  public void testEmptyOverrideFile() throws Exception {
+    ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(makeEmptyFile(), DEFAULT_FILE);
+    assertEquals(CURRENT_VERSION, data.getVersion());
+    assertEquals(TimeZone.getAvailableIDs().length, data.getAvailableIDs().length);
+  }
+
+  // A corrupt override file should fall back to the default file.
+  public void testCorruptOverrideFile() throws Exception {
+    ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(makeCorruptFile(), DEFAULT_FILE);
+    assertEquals(CURRENT_VERSION, data.getVersion());
+    assertEquals(TimeZone.getAvailableIDs().length, data.getAvailableIDs().length);
+  }
+
+  // Given no tzdata files we can use, we should fall back to built-in "GMT".
+  public void testNoGoodFile() throws Exception {
+    ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(makeEmptyFile());
+    assertEquals("missing", data.getVersion());
+    assertEquals(1, data.getAvailableIDs().length);
+    assertEquals("GMT", data.getAvailableIDs()[0]);
+  }
+
+  // Given a valid override file, we should find ourselves using that.
+  public void testGoodOverrideFile() throws Exception {
+    RandomAccessFile in = new RandomAccessFile(DEFAULT_FILE, "r");
+    byte[] content = new byte[(int) in.length()];
+    in.readFully(content);
+    content[6] = '9';
+    content[7] = '9';
+    content[8] = '9';
+    content[9] = '9';
+    content[10] = 'z';
+    in.close();
+
+    String goodFile = makeTemporaryFile(content);
+    try {
+      ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(goodFile, DEFAULT_FILE);
+      assertEquals("9999z", data.getVersion());
+      assertEquals(TimeZone.getAvailableIDs().length, data.getAvailableIDs().length);
+    } finally {
+      new File(goodFile).delete();
+    }
+  }
+
+  private static String makeCorruptFile() throws Exception {
+    return makeTemporaryFile("invalid content".getBytes());
+  }
+
+  private static String makeEmptyFile() throws Exception {
+    return makeTemporaryFile(new byte[0]);
+  }
+
+  private static String makeTemporaryFile(byte[] content) throws Exception {
+    File f = File.createTempFile("temp-", ".txt");
+    FileOutputStream fos = new FileOutputStream(f);
+    fos.write(content);
+    fos.close();
+    return f.getPath();
+  }
+}
diff --git a/luni/src/test/java/libcore/xml/PullParserTest.java b/luni/src/test/java/libcore/xml/PullParserTest.java
index 71125aa..c59b358 100644
--- a/luni/src/test/java/libcore/xml/PullParserTest.java
+++ b/luni/src/test/java/libcore/xml/PullParserTest.java
@@ -742,8 +742,42 @@
         assertEquals("foo", parser.getName());
     }
 
+    public void testEofInElementSpecRelaxed() throws Exception {
+        assertRelaxedParseFailure("<!DOCTYPE foo [<!ELEMENT foo (unterminated");
+    }
+
+    public void testEofInAttributeValue() throws Exception {
+        assertParseFailure("<!DOCTYPE foo [<!ATTLIST foo x y \"unterminated");
+    }
+
+    public void testEofInEntityValue() throws Exception {
+        assertParseFailure("<!DOCTYPE foo [<!ENTITY aaa \"unterminated");
+    }
+
+    public void testEofInStartTagAttributeValue() throws Exception {
+        assertParseFailure("<long foo=\"unterminated");
+    }
+
+    public void testEofInReadCharRelaxed() throws Exception {
+        assertRelaxedParseFailure("<!DOCTYPE foo [<!ELEMENT foo ()"); // EOF in read('>')
+    }
+
+    public void testEofAfterReadCharArrayRelaxed() throws Exception {
+        assertRelaxedParseFailure("<!DOCTYPE foo [<!ELEMENT foo EMPTY"); // EOF in read('>')
+    }
+
     private void assertParseFailure(String xml) throws Exception {
         XmlPullParser parser = newPullParser();
+        assertParseFailure(xml, parser);
+    }
+
+    private void assertRelaxedParseFailure(String xml) throws Exception {
+        XmlPullParser parser = newPullParser();
+        parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true);
+        assertParseFailure(xml, parser);
+    }
+
+    private void assertParseFailure(String xml, XmlPullParser parser) throws Exception {
         parser.setInput(new StringReader(xml));
         try {
             while (parser.next() != XmlPullParser.END_DOCUMENT) {
diff --git a/luni/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java b/luni/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
index 0281d02..afdce5d 100644
--- a/luni/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
+++ b/luni/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
@@ -77,6 +77,8 @@
 
     private final String jarName8 = "hyts_signed_sha512digest_sha512withecdsa.jar";
 
+    private final String authAttrsJar = "hyts_signed_authAttrs.jar";
+
     private final String entryName = "foo/bar/A.class";
 
     private final String entryName3 = "coucou/FileAccess.class";
@@ -603,6 +605,9 @@
 
         // SHA-512 digest, SHA512withECDSA signed JAR
         checkSignedJar(jarName8);
+
+        // JAR with a signature that has PKCS#7 Authenticated Attributes
+        checkSignedJar(authAttrsJar);
     }
 
     private void checkSignedJar(String jarName) throws Exception {
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
index d65dd4b..b1559f5 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
@@ -22,7 +22,6 @@
 
 package org.apache.harmony.crypto.tests.javax.crypto;
 
-import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
@@ -30,7 +29,6 @@
 import java.security.NoSuchProviderException;
 import java.security.Provider;
 import java.security.Security;
-import java.security.spec.DSAParameterSpec;
 import java.security.spec.PSSParameterSpec;
 import java.util.Arrays;
 
@@ -44,9 +42,6 @@
 
 import org.apache.harmony.crypto.tests.support.MyMacSpi;
 import org.apache.harmony.security.tests.support.SpiEngUtils;
-import org.apache.harmony.xnet.provider.jsse.NativeCryptoTest;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider;
 
 import junit.framework.TestCase;
 
@@ -891,46 +886,6 @@
         }
     }
 
-    public void test_getInstance_OpenSSL_ENGINE() throws Exception {
-        final String secret = "-HMAC-test1";
-        final byte[] testString = "testing123".getBytes();
-
-        Provider p = Security.getProvider(OpenSSLProvider.PROVIDER_NAME);
-        NativeCryptoTest.loadTestEngine();
-        OpenSSLEngine engine = OpenSSLEngine.getInstance(NativeCryptoTest.TEST_ENGINE_ID);
-
-        /*
-         * The "-HMAC-" prefix is a special prefix recognized by
-         * test_openssl_engine.cpp
-         */
-        SecretKey key1 = engine.getSecretKeyById(secret, "HmacSHA256");
-        SecretKey key1dupe = engine.getSecretKeyById(secret, "HmacSHA256");
-
-        /* Non-ENGINE-based SecretKey */
-        SecretKey key2 = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
-
-        /* The one that is ENGINE-based can't be equal to a non-ENGINE one. */
-        assertFalse(key1.equals(key2));
-        assertEquals(key1, key1dupe);
-        assertNull(key1.getFormat());
-        assertNull(key1.getEncoded());
-        assertEquals("RAW", key2.getFormat());
-        assertEquals(Arrays.toString(secret.getBytes()), Arrays.toString(key2.getEncoded()));
-
-        Mac mac1 = Mac.getInstance("HmacSHA256", p);
-        mac1.init(key1);
-        mac1.update(testString);
-        byte[] output1 = mac1.doFinal();
-        assertEquals(mac1.getMacLength(), output1.length);
-
-        Mac mac2 = Mac.getInstance("HmacSHA256", p);
-        mac2.init(key2);
-        mac2.update(testString);
-        byte[] output2 = mac2.doFinal();
-
-        assertEquals(Arrays.toString(output2), Arrays.toString(output1));
-    }
-
     class Mock_Mac extends Mac {
         protected Mock_Mac(MacSpi arg0, Provider arg1, String arg2) {
             super(arg0, arg1, arg2);
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/spec/GCMParameterSpecTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/spec/GCMParameterSpecTest.java
new file mode 100644
index 0000000..28b57fd
--- /dev/null
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/spec/GCMParameterSpecTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 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.
+ */
+
+package org.apache.harmony.crypto.tests.javax.crypto.spec;
+
+import java.util.Arrays;
+
+import javax.crypto.spec.GCMParameterSpec;
+
+import junit.framework.TestCase;
+
+public class GCMParameterSpecTest extends TestCase {
+    private static final byte[] TEST_IV = new byte[8];
+
+    public void testConstructor_IntByteArray_Success() throws Exception {
+        new GCMParameterSpec(8, TEST_IV);
+    }
+
+    public void testConstructor_IntByteArray_NegativeTLen_Failure() throws Exception {
+        try {
+            new GCMParameterSpec(-1, TEST_IV);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testConstructor_IntByteArray_NullIv_Failure() throws Exception {
+        try {
+            new GCMParameterSpec(8, null);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testConstructor_IntByteArrayWithOffsets_Success() throws Exception {
+        new GCMParameterSpec(8, TEST_IV, 0, TEST_IV.length);
+    }
+
+    public void testConstructor_IntByteArrayWithOffsets_NullIv_Failure() throws Exception {
+        try {
+            new GCMParameterSpec(8, null, 0, TEST_IV.length);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testConstructor_IntByteArrayWithOffsets_NegativeOffset_Failure() throws Exception {
+        try {
+            new GCMParameterSpec(8, TEST_IV, -1, TEST_IV.length);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testConstructor_IntByteArrayWithOffsets_TooLongLength_Failure() throws Exception {
+        try {
+            new GCMParameterSpec(8, TEST_IV, 0, TEST_IV.length + 1);
+            fail("Should throw IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testGetIV_Success() throws Exception {
+        GCMParameterSpec spec = new GCMParameterSpec(8, TEST_IV);
+
+        byte[] actual = spec.getIV();
+        assertEquals(Arrays.toString(TEST_IV), Arrays.toString(actual));
+
+        // XOR with 0xFF so we're sure we changed the array
+        for (int i = 0; i < actual.length; i++) {
+            actual[i] ^= 0xFF;
+        }
+
+        assertFalse("Changing the IV returned shouldn't change the parameter spec",
+                Arrays.equals(spec.getIV(), actual));
+        assertEquals(Arrays.toString(TEST_IV), Arrays.toString(spec.getIV()));
+    }
+
+    public void testGetIV_Subarray_Success() throws Exception {
+        GCMParameterSpec spec = new GCMParameterSpec(8, TEST_IV, 2, 4);
+        assertEquals(Arrays.toString(Arrays.copyOfRange(TEST_IV, 2, 6)),
+                Arrays.toString(spec.getIV()));
+    }
+
+    public void testGetTLen_Success() throws Exception {
+        GCMParameterSpec spec = new GCMParameterSpec(8, TEST_IV);
+        assertEquals(8, spec.getTLen());
+    }
+}
diff --git a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/Pattern2Test.java b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/Pattern2Test.java
index 389194a..ee8ecfa 100644
--- a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/Pattern2Test.java
+++ b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/Pattern2Test.java
@@ -28,784 +28,6 @@
  */
 public class Pattern2Test extends TestCase {
 
-    public void testSimpleMatch() throws PatternSyntaxException {
-        Pattern p = Pattern.compile("foo.*");
-
-        Matcher m1 = p.matcher("foo123");
-        assertTrue(m1.matches());
-        assertTrue(m1.find(0));
-        assertTrue(m1.lookingAt());
-
-        Matcher m2 = p.matcher("fox");
-        assertFalse(m2.matches());
-        assertFalse(m2.find(0));
-        assertFalse(m2.lookingAt());
-
-        assertTrue(Pattern.matches("foo.*", "foo123"));
-        assertFalse(Pattern.matches("foo.*", "fox"));
-
-        assertFalse(Pattern.matches("bar", "foobar"));
-
-        assertTrue(Pattern.matches("", ""));
-    }
-    public void testCursors() {
-        Pattern p;
-        Matcher m;
-
-        try {
-            p = Pattern.compile("foo");
-
-            m = p.matcher("foobar");
-            assertTrue(m.find());
-            assertEquals(0, m.start());
-            assertEquals(3, m.end());
-            assertFalse(m.find());
-
-            // Note: also testing reset here
-            m.reset();
-            assertTrue(m.find());
-            assertEquals(0, m.start());
-            assertEquals(3, m.end());
-            assertFalse(m.find());
-
-            m.reset("barfoobar");
-            assertTrue(m.find());
-            assertEquals(3, m.start());
-            assertEquals(6, m.end());
-            assertFalse(m.find());
-
-            m.reset("barfoo");
-            assertTrue(m.find());
-            assertEquals(3, m.start());
-            assertEquals(6, m.end());
-            assertFalse(m.find());
-
-            m.reset("foobarfoobarfoo");
-            assertTrue(m.find());
-            assertEquals(0, m.start());
-            assertEquals(3, m.end());
-            assertTrue(m.find());
-            assertEquals(6, m.start());
-            assertEquals(9, m.end());
-            assertTrue(m.find());
-            assertEquals(12, m.start());
-            assertEquals(15, m.end());
-            assertFalse(m.find());
-            assertTrue(m.find(0));
-            assertEquals(0, m.start());
-            assertEquals(3, m.end());
-            assertTrue(m.find(4));
-            assertEquals(6, m.start());
-            assertEquals(9, m.end());
-        } catch (PatternSyntaxException e) {
-            System.out.println(e.getMessage());
-            fail();
-        }
-    }
-    public void testGroups() throws PatternSyntaxException {
-        Pattern p;
-        Matcher m;
-
-        p = Pattern.compile("(p[0-9]*)#?(q[0-9]*)");
-
-        m = p.matcher("p1#q3p2q42p5p71p63#q888");
-        assertTrue(m.find());
-        assertEquals(0, m.start());
-        assertEquals(5, m.end());
-        assertEquals(2, m.groupCount());
-        assertEquals(0, m.start(0));
-        assertEquals(5, m.end(0));
-        assertEquals(0, m.start(1));
-        assertEquals(2, m.end(1));
-        assertEquals(3, m.start(2));
-        assertEquals(5, m.end(2));
-        assertEquals("p1#q3", m.group());
-        assertEquals("p1#q3", m.group(0));
-        assertEquals("p1", m.group(1));
-        assertEquals("q3", m.group(2));
-
-        assertTrue(m.find());
-        assertEquals(5, m.start());
-        assertEquals(10, m.end());
-        assertEquals(2, m.groupCount());
-        assertEquals(10, m.end(0));
-        assertEquals(5, m.start(1));
-        assertEquals(7, m.end(1));
-        assertEquals(7, m.start(2));
-        assertEquals(10, m.end(2));
-        assertEquals("p2q42", m.group());
-        assertEquals("p2q42", m.group(0));
-        assertEquals("p2", m.group(1));
-        assertEquals("q42", m.group(2));
-
-        assertTrue(m.find());
-        assertEquals(15, m.start());
-        assertEquals(23, m.end());
-        assertEquals(2, m.groupCount());
-        assertEquals(15, m.start(0));
-        assertEquals(23, m.end(0));
-        assertEquals(15, m.start(1));
-        assertEquals(18, m.end(1));
-        assertEquals(19, m.start(2));
-        assertEquals(23, m.end(2));
-        assertEquals("p63#q888", m.group());
-        assertEquals("p63#q888", m.group(0));
-        assertEquals("p63", m.group(1));
-        assertEquals("q888", m.group(2));
-        assertFalse(m.find());
-    }
-
-    public void testReplace() throws PatternSyntaxException {
-        Pattern p;
-        Matcher m;
-
-        // Note: examples from book,
-        // Hitchens, Ron, 2002, "Java NIO", O'Reilly, page 171
-        p = Pattern.compile("a*b");
-
-        m = p.matcher("aabfooaabfooabfoob");
-        assertTrue(m.replaceAll("-").equals("-foo-foo-foo-"));
-        assertTrue(m.replaceFirst("-").equals("-fooaabfooabfoob"));
-
-        /*
-         * p = Pattern.compile ("\\p{Blank}");
-         *
-         * m = p.matcher ("fee fie foe fum"); assertTrue
-         * (m.replaceFirst("-").equals ("fee-fie foe fum")); assertTrue
-         * (m.replaceAll("-").equals ("fee-fie-foe-fum"));
-         */
-
-        p = Pattern.compile("([bB])yte");
-
-        m = p.matcher("Byte for byte");
-        assertTrue(m.replaceFirst("$1ite").equals("Bite for byte"));
-        assertTrue(m.replaceAll("$1ite").equals("Bite for bite"));
-
-        p = Pattern.compile("\\d\\d\\d\\d([- ])");
-
-        m = p.matcher("card #1234-5678-1234");
-        assertTrue(m.replaceFirst("xxxx$1").equals("card #xxxx-5678-1234"));
-        assertTrue(m.replaceAll("xxxx$1").equals("card #xxxx-xxxx-1234"));
-
-        p = Pattern.compile("(up|left)( *)(right|down)");
-
-        m = p.matcher("left right, up down");
-        assertTrue(m.replaceFirst("$3$2$1").equals("right left, up down"));
-        assertTrue(m.replaceAll("$3$2$1").equals("right left, down up"));
-
-        p = Pattern.compile("([CcPp][hl]e[ea]se)");
-
-        m = p.matcher("I want cheese. Please.");
-        assertTrue(m.replaceFirst("<b> $1 </b>").equals(
-                "I want <b> cheese </b>. Please."));
-        assertTrue(m.replaceAll("<b> $1 </b>").equals(
-                "I want <b> cheese </b>. <b> Please </b>."));
-    }
-
-    public void testEscapes() throws PatternSyntaxException {
-        Pattern p;
-        Matcher m;
-
-        // Test \\ sequence
-        p = Pattern.compile("([a-z]+)\\\\([a-z]+);");
-        m = p.matcher("fred\\ginger;abbott\\costello;jekell\\hyde;");
-        assertTrue(m.find());
-        assertEquals("fred", m.group(1));
-        assertEquals("ginger", m.group(2));
-        assertTrue(m.find());
-        assertEquals("abbott", m.group(1));
-        assertEquals("costello", m.group(2));
-        assertTrue(m.find());
-        assertEquals("jekell", m.group(1));
-        assertEquals("hyde", m.group(2));
-        assertFalse(m.find());
-
-        // Test \n, \t, \r, \f, \e, \a sequences
-        p = Pattern.compile("([a-z]+)[\\n\\t\\r\\f\\e\\a]+([a-z]+)");
-        m = p.matcher("aa\nbb;cc\u0009\rdd;ee\u000C\u001Bff;gg\n\u0007hh");
-        assertTrue(m.find());
-        assertEquals("aa", m.group(1));
-        assertEquals("bb", m.group(2));
-        assertTrue(m.find());
-        assertEquals("cc", m.group(1));
-        assertEquals("dd", m.group(2));
-        assertTrue(m.find());
-        assertEquals("ee", m.group(1));
-        assertEquals("ff", m.group(2));
-        assertTrue(m.find());
-        assertEquals("gg", m.group(1));
-        assertEquals("hh", m.group(2));
-        assertFalse(m.find());
-
-        // Test \\u and \\x sequences
-/*        p = Pattern.compile("([0-9]+)[\\u0020:\\x21];");
-        m = p.matcher("11:;22 ;33-;44!;");
-        assertTrue(m.find());
-        assertEquals("11", m.group(1));
-        assertTrue(m.find());
-        assertEquals("22", m.group(1));
-        assertTrue(m.find());
-        assertEquals("44", m.group(1));
-        assertFalse(m.find());
-*/
-        // Test invalid unicode sequences
-/*        try {
-            p = Pattern.compile("\\u");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\u;");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\u002");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\u002;");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        // Test invalid hex sequences
-        try {
-            p = Pattern.compile("\\x");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\x;");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\xa");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\xa;");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-*/
-        // Test \0 (octal) sequences (1, 2 and 3 digit)
-        p = Pattern.compile("([0-9]+)[\\07\\040\\0160];");
-        m = p.matcher("11\u0007;22:;33 ;44p;");
-        assertTrue(m.find());
-        assertEquals("11", m.group(1));
-        assertTrue(m.find());
-        assertEquals("33", m.group(1));
-        assertTrue(m.find());
-        assertEquals("44", m.group(1));
-        assertFalse(m.find());
-
-        // Test invalid octal sequences
-        try {
-            p = Pattern.compile("\\08");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        //originally contributed test did not check the result
-        //TODO: check what RI does here
-//        try {
-//            p = Pattern.compile("\\0477");
-//            fail("PatternSyntaxException expected");
-//        } catch (PatternSyntaxException e) {
-//        }
-
-        try {
-            p = Pattern.compile("\\0");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\0;");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-
-        // Test \c (control character) sequence
-        p = Pattern.compile("([0-9]+)[\\cA\\cB\\cC\\cD];");
-        m = p.matcher("11\u0001;22:;33\u0002;44p;55\u0003;66\u0004;");
-        assertTrue(m.find());
-        assertEquals("11", m.group(1));
-        assertTrue(m.find());
-        assertEquals("33", m.group(1));
-        assertTrue(m.find());
-        assertEquals("55", m.group(1));
-        assertTrue(m.find());
-        assertEquals("66", m.group(1));
-        assertFalse(m.find());
-
-        // More thorough control escape test
-        // Ensure that each escape matches exactly the corresponding
-        // character
-        // code and no others (well, from 0-255 at least)
-        int i, j;
-        for (i = 0; i < 26; i++) {
-            p = Pattern.compile("\\c" + Character.toString((char) ('A' + i)));
-            int match_char = -1;
-            for (j = 0; j < 255; j++) {
-                m = p.matcher(Character.toString((char) j));
-                if (m.matches()) {
-                    assertEquals(-1, match_char);
-                    match_char = j;
-                }
-            }
-            assertTrue(match_char == i + 1);
-        }
-
-        // Test invalid control escapes
-// BEGIN android-removed
-// ICU doesn't complain about illegal control sequences
-//        try {
-//            p = Pattern.compile("\\c");
-//            fail("PatternSyntaxException expected");
-//        } catch (PatternSyntaxException e) {
-//        }
-// END android-removed
-
-        //originally contributed test did not check the result
-        //TODO: check what RI does here
-//        try {
-//            p = Pattern.compile("\\c;");
-//            fail("PatternSyntaxException expected");
-//        } catch (PatternSyntaxException e) {
-//        }
-//
-//        try {
-//            p = Pattern.compile("\\ca;");
-//            fail("PatternSyntaxException expected");
-//        } catch (PatternSyntaxException e) {
-//        }
-//
-//        try {
-//            p = Pattern.compile("\\c4;");
-//            fail("PatternSyntaxException expected");
-//        } catch (PatternSyntaxException e) {
-//        }
-    }
-    public void testCharacterClasses() throws PatternSyntaxException {
-        Pattern p;
-        Matcher m;
-
-        // Test one character range
-        p = Pattern.compile("[p].*[l]");
-        m = p.matcher("paul");
-        assertTrue(m.matches());
-        m = p.matcher("pool");
-        assertTrue(m.matches());
-        m = p.matcher("pong");
-        assertFalse(m.matches());
-        m = p.matcher("pl");
-        assertTrue(m.matches());
-
-        // Test two character range
-        p = Pattern.compile("[pm].*[lp]");
-        m = p.matcher("prop");
-        assertTrue(m.matches());
-        m = p.matcher("mall");
-        assertTrue(m.matches());
-        m = p.matcher("pong");
-        assertFalse(m.matches());
-        m = p.matcher("pill");
-        assertTrue(m.matches());
-
-        // Test range including [ and ]
-        p = Pattern.compile("[<\\[].*[\\]>]");
-        m = p.matcher("<foo>");
-        assertTrue(m.matches());
-        m = p.matcher("[bar]");
-        assertTrue(m.matches());
-        m = p.matcher("{foobar]");
-        assertFalse(m.matches());
-        m = p.matcher("<pill]");
-        assertTrue(m.matches());
-
-        // Test range using ^
-        p = Pattern.compile("[^bc][a-z]+[tr]");
-        m = p.matcher("pat");
-        assertTrue(m.matches());
-        m = p.matcher("liar");
-        assertTrue(m.matches());
-        m = p.matcher("car");
-        assertFalse(m.matches());
-        m = p.matcher("gnat");
-        assertTrue(m.matches());
-
-        // Test character range using -
-        p = Pattern.compile("[a-z]_+[a-zA-Z]-+[0-9p-z]");
-        m = p.matcher("d__F-8");
-        assertTrue(m.matches());
-        m = p.matcher("c_a-q");
-        assertTrue(m.matches());
-        m = p.matcher("a__R-a");
-        assertFalse(m.matches());
-        m = p.matcher("r_____d-----5");
-        assertTrue(m.matches());
-
-        // Test range using unicode characters and unicode and hex escapes
-        p = Pattern.compile("[\\u1234-\\u2345]_+[a-z]-+[\u0001-\\x11]");
-        m = p.matcher("\u2000_q-\u0007");
-        assertTrue(m.matches());
-        m = p.matcher("\u1234_z-\u0001");
-        assertTrue(m.matches());
-        m = p.matcher("r_p-q");
-        assertFalse(m.matches());
-        m = p.matcher("\u2345_____d-----\n");
-        assertTrue(m.matches());
-
-// BEGIN android-removed
-// The "---" collides with ICU's "--" operator and is likely to be a user error
-// anyway, so we simply comment this one out.
-//        // Test ranges including the "-" character
-//        p = Pattern.compile("[\\*-/]_+[---]!+[--AP]");
-//        m = p.matcher("-_-!!A");
-//        assertTrue(m.matches());
-//        m = p.matcher("\u002b_-!!!-");
-//        assertTrue(m.matches());
-//        m = p.matcher("!_-!@");
-//        assertFalse(m.matches());
-//        m = p.matcher(",______-!!!!!!!P");
-//        assertTrue(m.matches());
-// END android-removed
-
-        // Test nested ranges
-        p = Pattern.compile("[pm[t]][a-z]+[[r]lp]");
-        m = p.matcher("prop");
-        assertTrue(m.matches());
-        m = p.matcher("tsar");
-        assertTrue(m.matches());
-        m = p.matcher("pong");
-        assertFalse(m.matches());
-        m = p.matcher("moor");
-        assertTrue(m.matches());
-
-        // Test character class intersection with &&
-        // TODO: figure out what x&&y or any class with a null intersection
-        // set (like [[a-c]&&[d-f]]) might mean. It doesn't mean "match
-        // nothing" and doesn't mean "match anything" so I'm stumped.
-        p = Pattern.compile("[[a-p]&&[g-z]]+-+[[a-z]&&q]-+[x&&[a-z]]-+");
-        m = p.matcher("h--q--x--");
-        assertTrue(m.matches());
-        m = p.matcher("hog--q-x-");
-        assertTrue(m.matches());
-        m = p.matcher("ape--q-x-");
-        assertFalse(m.matches());
-        m = p.matcher("mop--q-x----");
-        assertTrue(m.matches());
-
-        // Test error cases with &&
-// BEGIN android-removed
-// This is more of a bug, and ICU doesn't have this behavior.
-//            p = Pattern.compile("[&&[xyz]]");
-//            m = p.matcher("&");
-//            // System.out.println(m.matches());
-//            m = p.matcher("x");
-//            // System.out.println(m.matches());
-//            m = p.matcher("y");
-//            // System.out.println(m.matches());
-// END android-removed
-            p = Pattern.compile("[[xyz]&[axy]]");
-            m = p.matcher("x");
-            // System.out.println(m.matches());
-            m = p.matcher("z");
-            // System.out.println(m.matches());
-            m = p.matcher("&");
-            // System.out.println(m.matches());
-            p = Pattern.compile("[abc[123]&&[345]def]");
-            m = p.matcher("a");
-            // System.out.println(m.matches());
-
-// BEGIN android-removed
-// This is more of a bug, and ICU doesn't have this behavior.
-//            p = Pattern.compile("[[xyz]&&]");
-// END android-removed
-            p = Pattern.compile("[[abc]&]");
-
-        try {
-            p = Pattern.compile("[[abc]&&");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        p = Pattern.compile("[[abc]\\&&[xyz]]");
-
-        p = Pattern.compile("[[abc]&\\&[xyz]]");
-
-        // Test 3-way intersection
-        p = Pattern.compile("[[a-p]&&[g-z]&&[d-k]]");
-        m = p.matcher("g");
-        assertTrue(m.matches());
-        m = p.matcher("m");
-        assertFalse(m.matches());
-
-        // Test nested intersection
-        p = Pattern.compile("[[[a-p]&&[g-z]]&&[d-k]]");
-        m = p.matcher("g");
-        assertTrue(m.matches());
-        m = p.matcher("m");
-        assertFalse(m.matches());
-
-        // Test character class subtraction with && and ^
-        p = Pattern.compile("[[a-z]&&[^aeiou]][aeiou][[^xyz]&&[a-z]]");
-        m = p.matcher("pop");
-        assertTrue(m.matches());
-        m = p.matcher("tag");
-        assertTrue(m.matches());
-        m = p.matcher("eat");
-        assertFalse(m.matches());
-        m = p.matcher("tax");
-        assertFalse(m.matches());
-        m = p.matcher("zip");
-        assertTrue(m.matches());
-
-        // Test . (DOT), with and without DOTALL
-        // Note: DOT not allowed in character classes
-        p = Pattern.compile(".+/x.z");
-        m = p.matcher("!$/xyz");
-        assertTrue(m.matches());
-        m = p.matcher("%\n\r/x\nz");
-        assertFalse(m.matches());
-        p = Pattern.compile(".+/x.z", Pattern.DOTALL);
-        m = p.matcher("%\n\r/x\nz");
-        assertTrue(m.matches());
-
-        // Test \d (digit)
-        p = Pattern.compile("\\d+[a-z][\\dx]");
-        m = p.matcher("42a6");
-        assertTrue(m.matches());
-        m = p.matcher("21zx");
-        assertTrue(m.matches());
-        m = p.matcher("ab6");
-        assertFalse(m.matches());
-        m = p.matcher("56912f9");
-        assertTrue(m.matches());
-
-        // Test \D (not a digit)
-        p = Pattern.compile("\\D+[a-z]-[\\D3]");
-        m = p.matcher("za-p");
-        assertTrue(m.matches());
-        m = p.matcher("%!e-3");
-        assertTrue(m.matches());
-        m = p.matcher("9a-x");
-        assertFalse(m.matches());
-        m = p.matcher("\u1234pp\ny-3");
-        assertTrue(m.matches());
-
-        // Test \s (whitespace)
-        p = Pattern.compile("<[a-zA-Z]+\\s+[0-9]+[\\sx][^\\s]>");
-        m = p.matcher("<cat \t1\fx>");
-        assertTrue(m.matches());
-        m = p.matcher("<cat \t1\f >");
-        assertFalse(m.matches());
-        m = p
-                .matcher("xyz <foo\n\r22 5> <pp \t\n\f\r \u000b41x\u1234><pp \nx7\rc> zzz");
-        assertTrue(m.find());
-        assertTrue(m.find());
-        assertFalse(m.find());
-
-        // Test \S (not whitespace)
-        p = Pattern.compile("<[a-z] \\S[0-9][\\S\n]+[^\\S]221>");
-        m = p.matcher("<f $0**\n** 221>");
-        assertTrue(m.matches());
-        m = p.matcher("<x 441\t221>");
-        assertTrue(m.matches());
-        m = p.matcher("<z \t9\ng 221>");
-        assertFalse(m.matches());
-        m = p.matcher("<z 60\ngg\u1234\f221>");
-        assertTrue(m.matches());
-        p = Pattern.compile("<[a-z] \\S[0-9][\\S\n]+[^\\S]221[\\S&&[^abc]]>");
-        m = p.matcher("<f $0**\n** 221x>");
-        assertTrue(m.matches());
-        m = p.matcher("<x 441\t221z>");
-        assertTrue(m.matches());
-        m = p.matcher("<x 441\t221 >");
-        assertFalse(m.matches());
-        m = p.matcher("<x 441\t221c>");
-        assertFalse(m.matches());
-        m = p.matcher("<z \t9\ng 221x>");
-        assertFalse(m.matches());
-        m = p.matcher("<z 60\ngg\u1234\f221\u0001>");
-        assertTrue(m.matches());
-
-        // Test \w (ascii word)
-        p = Pattern.compile("<\\w+\\s[0-9]+;[^\\w]\\w+/[\\w$]+;");
-        m = p.matcher("<f1 99;!foo5/a$7;");
-        assertTrue(m.matches());
-        m = p.matcher("<f$ 99;!foo5/a$7;");
-        assertFalse(m.matches());
-        m = p
-                .matcher("<abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 99;!foo5/a$7;");
-        assertTrue(m.matches());
-
-        // Test \W (not an ascii word)
-        p = Pattern.compile("<\\W\\w+\\s[0-9]+;[\\W_][^\\W]+\\s[0-9]+;");
-        m = p.matcher("<$foo3\n99;_bar\t0;");
-        assertTrue(m.matches());
-        m = p.matcher("<hh 99;_g 0;");
-        assertFalse(m.matches());
-        m = p.matcher("<*xx\t00;^zz\f11;");
-        assertTrue(m.matches());
-
-        // Test x|y pattern
-        // TODO
-    }
-    public void testPOSIXGroups() throws PatternSyntaxException {
-        Pattern p;
-        Matcher m;
-
-        // Test POSIX groups using \p and \P (in the group and not in the group)
-        // Groups are Lower, Upper, ASCII, Alpha, Digit, XDigit, Alnum, Punct,
-        // Graph, Print, Blank, Space, Cntrl
-        // Test \p{Lower}
-        /*
-         * FIXME: Requires complex range processing
-         * p = Pattern.compile("<\\p{Lower}\\d\\P{Lower}:[\\p{Lower}Z]\\s[^\\P{Lower}]>");
-         * m = p.matcher("<a4P:g x>"); assertTrue(m.matches()); m =
-         * p.matcher("<p4%:Z\tq>"); assertTrue(m.matches()); m =
-         * p.matcher("<A6#:e e>"); assertFalse(m.matches());
-         */
-        p = Pattern.compile("\\p{Lower}+");
-        m = p.matcher("abcdefghijklmnopqrstuvwxyz");
-        assertTrue(m.matches());
-
-        // Invalid uses of \p{Lower}
-        try {
-            p = Pattern.compile("\\p");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\p;");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\p{");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\p{;");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\p{Lower");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\p{Lower;");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        // Test \p{Upper}
-        /*
-         * FIXME: Requires complex range processing
-         * p = Pattern.compile("<\\p{Upper}\\d\\P{Upper}:[\\p{Upper}z]\\s[^\\P{Upper}]>");
-         * m = p.matcher("<A4p:G X>"); assertTrue(m.matches()); m =
-         * p.matcher("<P4%:z\tQ>"); assertTrue(m.matches()); m =
-         * p.matcher("<a6#:E E>"); assertFalse(m.matches());
-         */
-        p = Pattern.compile("\\p{Upper}+");
-        m = p.matcher("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
-        assertTrue(m.matches());
-
-        // Invalid uses of \p{Upper}
-        try {
-            p = Pattern.compile("\\p{Upper");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\p{Upper;");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        // Test \p{ASCII}
-        /*
-         * FIXME: Requires complex range processing p = Pattern.compile("<\\p{ASCII}\\d\\P{ASCII}:[\\p{ASCII}\u1234]\\s[^\\P{ASCII}]>");
-         * m = p.matcher("<A4\u0080:G X>"); assertTrue(m.matches()); m =
-         * p.matcher("<P4\u00ff:\u1234\t\n>"); assertTrue(m.matches()); m =
-         * p.matcher("<\u00846#:E E>"); assertFalse(m.matches())
-         */
-        int i;
-        p = Pattern.compile("\\p{ASCII}");
-        for (i = 0; i < 0x80; i++) {
-            m = p.matcher(Character.toString((char) i));
-            assertTrue(m.matches());
-        }
-        for (; i < 0xff; i++) {
-            m = p.matcher(Character.toString((char) i));
-            assertFalse(m.matches());
-        }
-
-        // Invalid uses of \p{ASCII}
-        try {
-            p = Pattern.compile("\\p{ASCII");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        try {
-            p = Pattern.compile("\\p{ASCII;");
-            fail("PatternSyntaxException expected");
-        } catch (PatternSyntaxException e) {
-        }
-
-        // Test \p{Alpha}
-        // TODO
-
-        // Test \p{Digit}
-        // TODO
-
-        // Test \p{XDigit}
-        // TODO
-
-        // Test \p{Alnum}
-        // TODO
-
-        // Test \p{Punct}
-        // TODO
-
-        // Test \p{Graph}
-        // TODO
-
-        // Test \p{Print}
-        // TODO
-
-        // Test \p{Blank}
-        // TODO
-
-        // Test \p{Space}
-        // TODO
-
-        // Test \p{Cntrl}
-        // TODO
-    }
     public void testUnicodeCategories() throws PatternSyntaxException {
         // Test Unicode categories using \p and \P
         // One letter codes: L, M, N, P, S, Z, C
@@ -906,75 +128,6 @@
         }
     }
 
-    public void testUnicodeBlocks() throws PatternSyntaxException {
-        Pattern p;
-        Matcher m;
-        int i, j;
-
-        // Test Unicode blocks using \p and \P
-        // FIXME:
-        // Note that LatinExtended-B and ArabicPresentations-B are unrecognized
-        // by the reference JDK.
-        for (i = 0; i < UBlocks.length; i++) {
-            /*
-             * p = Pattern.compile("\\p{"+UBlocks[i].name+"}");
-             *
-             * if (UBlocks[i].low > 0) { m =
-             * p.matcher(Character.toString((char)(UBlocks[i].low-1)));
-             * assertFalse(m.matches()); } for (j=UBlocks[i].low; j <=
-             * UBlocks[i].high; j++) { m =
-             * p.matcher(Character.toString((char)j));
-             * assertTrue(m.matches()); } if (UBlocks[i].high < 0xFFFF) { m =
-             * p.matcher(Character.toString((char)(UBlocks[i].high+1)));
-             * assertFalse(m.matches()); }
-             *
-             * p = Pattern.compile("\\P{"+UBlocks[i].name+"}");
-             *
-             * if (UBlocks[i].low > 0) { m =
-             * p.matcher(Character.toString((char)(UBlocks[i].low-1)));
-             * assertTrue(m.matches()); } for (j=UBlocks[i].low; j <
-             * UBlocks[i].high; j++) { m =
-             * p.matcher(Character.toString((char)j));
-             * assertFalse(m.matches()); } if (UBlocks[i].high < 0xFFFF) { m =
-             * p.matcher(Character.toString((char)(UBlocks[i].high+1)));
-             * assertTrue(m.matches()); }
-             */
-
-            p = Pattern.compile("\\p{In" + UBlocks[i].name + "}");
-// BEGIN android-changed
-// Added the name of the block under test to the assertion to get more output.
-
-            if (UBlocks[i].low > 0) {
-                m = p.matcher(Character.toString((char) (UBlocks[i].low - 1)));
-                assertFalse(UBlocks[i].name, m.matches());
-            }
-            for (j = UBlocks[i].low; j <= UBlocks[i].high; j++) {
-                m = p.matcher(Character.toString((char) j));
-                assertTrue(UBlocks[i].name, m.matches());
-            }
-            if (UBlocks[i].high < 0xFFFF) {
-                m = p.matcher(Character.toString((char) (UBlocks[i].high + 1)));
-                assertFalse(UBlocks[i].name, m.matches());
-            }
-
-            p = Pattern.compile("\\P{In" + UBlocks[i].name + "}");
-
-            if (UBlocks[i].low > 0) {
-                m = p.matcher(Character.toString((char) (UBlocks[i].low - 1)));
-                assertTrue(UBlocks[i].name, m.matches());
-            }
-            for (j = UBlocks[i].low; j < UBlocks[i].high; j++) {
-                m = p.matcher(Character.toString((char) j));
-                assertFalse(UBlocks[i].name, m.matches());
-            }
-            if (UBlocks[i].high < 0xFFFF) {
-                m = p.matcher(Character.toString((char) (UBlocks[i].high + 1)));
-                assertTrue(UBlocks[i].name, m.matches());
-            }
-
-// END android-changed
-        }
-    }
     public void testCapturingGroups() throws PatternSyntaxException {
         Pattern p;
         Matcher m;
@@ -1142,436 +295,4 @@
         // Test negative lookbehind using (?<!...)
         // TODO
     }
-    public void testMisc() throws PatternSyntaxException {
-        Pattern p;
-        Matcher m;
-
-        // Test (?>...)
-        // TODO
-
-        // Test (?onflags-offflags)
-        // Valid flags are i,m,d,s,u,x
-        // TODO
-
-        // Test (?onflags-offflags:...)
-        // TODO
-
-        // Test \Q, \E
-        p = Pattern.compile("[a-z]+;\\Q[a-z]+;\\Q(foo.*);\\E[0-9]+");
-        m = p.matcher("abc;[a-z]+;\\Q(foo.*);411");
-        assertTrue(m.matches());
-        m = p.matcher("abc;def;foo42;555");
-        assertFalse(m.matches());
-        m = p.matcher("abc;\\Qdef;\\Qfoo99;\\E123");
-        assertFalse(m.matches());
-
-        p = Pattern.compile("[a-z]+;(foo[0-9]-\\Q(...)\\E);[0-9]+");
-        m = p.matcher("abc;foo5-(...);123");
-        assertTrue(m.matches());
-        assertEquals("foo5-(...)", m.group(1));
-        m = p.matcher("abc;foo9-(xxx);789");
-        assertFalse(m.matches());
-
-        p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q$-\\E]+);[0-9]+");
-        m = p.matcher("abc;bar0-def$-;123");
-        assertTrue(m.matches());
-
-        // FIXME:
-        // This should work the same as the pattern above but fails with the
-        // the reference JDK
-        p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q-$\\E]+);[0-9]+");
-        m = p.matcher("abc;bar0-def$-;123");
-        // assertTrue(m.matches());
-
-        // FIXME:
-        // This should work too .. it looks as if just about anything that
-        // has more
-        // than one character between \Q and \E is broken in the the reference JDK
-        p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q[0-9]\\E]+);[0-9]+");
-        m = p.matcher("abc;bar0-def[99]-]0x[;123");
-        // assertTrue(m.matches());
-
-        // This is the same as above but with explicit escapes .. and this
-        // does work
-        // on the the reference JDK
-        p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\[0\\-9\\]]+);[0-9]+");
-        m = p.matcher("abc;bar0-def[99]-]0x[;123");
-        assertTrue(m.matches());
-
-        // Test #<comment text>
-        // TODO
-    }
-    public void testCompile1() throws PatternSyntaxException {
-        Pattern pattern = Pattern
-                .compile("[0-9A-Za-z][0-9A-Za-z\\x2e\\x3a\\x2d\\x5f]*");
-        String name = "iso-8859-1";
-        assertTrue(pattern.matcher(name).matches());
-    }
-    public void testCompile2() throws PatternSyntaxException {
-        String findString = "\\Qimport\\E";
-
-        Pattern pattern = Pattern.compile(findString, 0);
-        Matcher matcher = pattern.matcher(new String(
-                "import a.A;\n\n import b.B;\nclass C {}"));
-
-        assertTrue(matcher.find(0));
-    }
-    public void testCompile3() throws PatternSyntaxException {
-        Pattern p;
-        Matcher m;
-        p = Pattern.compile("a$");
-        m = p.matcher("a\n");
-        assertTrue(m.find());
-        assertEquals("a", m.group());
-        assertFalse(m.find());
-
-        p = Pattern.compile("(a$)");
-        m = p.matcher("a\n");
-        assertTrue(m.find());
-        assertEquals("a", m.group());
-        assertEquals("a", m.group(1));
-        assertFalse(m.find());
-
-        p = Pattern.compile("^.*$", Pattern.MULTILINE);
-
-        m = p.matcher("a\n");
-        assertTrue(m.find());
-        // System.out.println("["+m.group()+"]");
-        assertEquals("a", m.group());
-        assertFalse(m.find());
-
-        m = p.matcher("a\nb\n");
-        assertTrue(m.find());
-        // System.out.println("["+m.group()+"]");
-        assertEquals("a", m.group());
-        assertTrue(m.find());
-        // System.out.println("["+m.group()+"]");
-        assertEquals("b", m.group());
-        assertFalse(m.find());
-
-        m = p.matcher("a\nb");
-        assertTrue(m.find());
-        // System.out.println("["+m.group()+"]");
-        assertEquals("a", m.group());
-        assertTrue(m.find());
-        assertEquals("b", m.group());
-        assertFalse(m.find());
-
-        m = p.matcher("\naa\r\nbb\rcc\n\n");
-        assertTrue(m.find());
-        // System.out.println("["+m.group()+"]");
-        assertTrue(m.group().equals(""));
-        assertTrue(m.find());
-        // System.out.println("["+m.group()+"]");
-        assertEquals("aa", m.group());
-        assertTrue(m.find());
-        // System.out.println("["+m.group()+"]");
-        assertEquals("bb", m.group());
-        assertTrue(m.find());
-        // System.out.println("["+m.group()+"]");
-        assertEquals("cc", m.group());
-        assertTrue(m.find());
-        // System.out.println("["+m.group()+"]");
-        assertTrue(m.group().equals(""));
-        assertFalse(m.find());
-
-        m = p.matcher("a");
-        assertTrue(m.find());
-        assertEquals("a", m.group());
-        assertFalse(m.find());
-
-// BEGIN android-removed
-// Makes no sense to duplicate this weird behavior
-//        m = p.matcher("");
-//        // FIXME: This matches the reference behaviour but is
-//        // inconsistent with matching "a" - ie. the end of the
-//        // target string should match against $ always but this
-//        // appears to work with the null string only when not in
-//        // multiline mode (see below)
-//        assertFalse(m.find());
-// END android-removed
-
-        p = Pattern.compile("^.*$");
-        m = p.matcher("");
-        assertTrue(m.find());
-        assertTrue(m.group().equals(""));
-        assertFalse(m.find());
-    }
-    public void testCompile4() throws PatternSyntaxException {
-        String findString = "\\Qpublic\\E";
-        StringBuffer text = new StringBuffer("    public class Class {\n"
-                + "    public class Class {");
-
-        Pattern pattern = Pattern.compile(findString, 0);
-        Matcher matcher = pattern.matcher(text);
-
-        boolean found = matcher.find();
-        assertTrue(found);
-        assertEquals(4, matcher.start());
-        if (found) {
-            // modify text
-            text.delete(0, text.length());
-            text.append("Text have been changed.");
-            matcher.reset(text);
-        }
-
-        found = matcher.find();
-        assertFalse(found);
-    }
-    public void testCompile5() throws PatternSyntaxException {
-        Pattern p = Pattern.compile("^[0-9]");
-        String s[] = p.split("12", -1);
-        assertEquals("", s[0]);
-        assertEquals("2", s[1]);
-        assertEquals(2, s.length);
-    }
-
-    //      public void testCompile6() {
-    //        String regex = "[\\p{L}[\\p{Mn}[\\p{Pc}[\\p{Nd}[\\p{Nl}[\\p{Sc}]]]]]]+";
-    //        String regex = "[\\p{L}\\p{Mn}\\p{Pc}\\p{Nd}\\p{Nl}\\p{Sc}]+";
-    //        try {
-    //            Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
-    //            assertTrue(true);
-    //        } catch (PatternSyntaxException e) {
-    //            System.out.println(e.getMessage());
-    //            assertTrue(false);
-    //        }
-    //    }
-
-    private static class UBInfo {
-        public UBInfo(int low, int high, String name) {
-            this.name = name;
-            this.low = low;
-            this.high = high;
-        }
-
-        public String name;
-
-        public int low, high;
-    }
-
-    // A table representing the unicode categories
-    //private static UBInfo[] UCategories = {
-    // Lu
-    // Ll
-    // Lt
-    // Lm
-    // Lo
-    // Mn
-    // Mc
-    // Me
-    // Nd
-    // Nl
-    // No
-    // Pc
-    // Pd
-    // Ps
-    // Pe
-    // Pi
-    // Pf
-    // Po
-    // Sm
-    // Sc
-    // Sk
-    // So
-    // Zs
-    // Zl
-    // Zp
-    // Cc
-    // Cf
-    // Cs
-    // Co
-    // Cn
-    //};
-
-    // A table representing the unicode character blocks
-    private static UBInfo[] UBlocks = {
-    /* 0000; 007F; Basic Latin */
-    new UBInfo(0x0000, 0x007F, "BasicLatin"), // Character.UnicodeBlock.BASIC_LATIN
-            /* 0080; 00FF; Latin-1 Supplement */
-            new UBInfo(0x0080, 0x00FF, "Latin-1Supplement"), // Character.UnicodeBlock.LATIN_1_SUPPLEMENT
-            /* 0100; 017F; Latin Extended-A */
-            new UBInfo(0x0100, 0x017F, "LatinExtended-A"), // Character.UnicodeBlock.LATIN_EXTENDED_A
-            /* 0180; 024F; Latin Extended-B */
-            // new UBInfo (0x0180,0x024F,"InLatinExtended-B"), //
-            // Character.UnicodeBlock.LATIN_EXTENDED_B
-            /* 0250; 02AF; IPA Extensions */
-            new UBInfo(0x0250, 0x02AF, "IPAExtensions"), // Character.UnicodeBlock.IPA_EXTENSIONS
-            /* 02B0; 02FF; Spacing Modifier Letters */
-            new UBInfo(0x02B0, 0x02FF, "SpacingModifierLetters"), // Character.UnicodeBlock.SPACING_MODIFIER_LETTERS
-            /* 0300; 036F; Combining Diacritical Marks */
-            new UBInfo(0x0300, 0x036F, "CombiningDiacriticalMarks"), // Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS
-            /* 0370; 03FF; Greek */
-            new UBInfo(0x0370, 0x03FF, "Greek"), // Character.UnicodeBlock.GREEK
-            /* 0400; 04FF; Cyrillic */
-            new UBInfo(0x0400, 0x04FF, "Cyrillic"), // Character.UnicodeBlock.CYRILLIC
-            /* 0530; 058F; Armenian */
-            new UBInfo(0x0530, 0x058F, "Armenian"), // Character.UnicodeBlock.ARMENIAN
-            /* 0590; 05FF; Hebrew */
-            new UBInfo(0x0590, 0x05FF, "Hebrew"), // Character.UnicodeBlock.HEBREW
-            /* 0600; 06FF; Arabic */
-            new UBInfo(0x0600, 0x06FF, "Arabic"), // Character.UnicodeBlock.ARABIC
-            /* 0700; 074F; Syriac */
-            new UBInfo(0x0700, 0x074F, "Syriac"), // Character.UnicodeBlock.SYRIAC
-            /* 0780; 07BF; Thaana */
-            new UBInfo(0x0780, 0x07BF, "Thaana"), // Character.UnicodeBlock.THAANA
-            /* 0900; 097F; Devanagari */
-            new UBInfo(0x0900, 0x097F, "Devanagari"), // Character.UnicodeBlock.DEVANAGARI
-            /* 0980; 09FF; Bengali */
-            new UBInfo(0x0980, 0x09FF, "Bengali"), // Character.UnicodeBlock.BENGALI
-            /* 0A00; 0A7F; Gurmukhi */
-            new UBInfo(0x0A00, 0x0A7F, "Gurmukhi"), // Character.UnicodeBlock.GURMUKHI
-            /* 0A80; 0AFF; Gujarati */
-            new UBInfo(0x0A80, 0x0AFF, "Gujarati"), // Character.UnicodeBlock.GUJARATI
-            /* 0B00; 0B7F; Oriya */
-            new UBInfo(0x0B00, 0x0B7F, "Oriya"), // Character.UnicodeBlock.ORIYA
-            /* 0B80; 0BFF; Tamil */
-            new UBInfo(0x0B80, 0x0BFF, "Tamil"), // Character.UnicodeBlock.TAMIL
-            /* 0C00; 0C7F; Telugu */
-            new UBInfo(0x0C00, 0x0C7F, "Telugu"), // Character.UnicodeBlock.TELUGU
-            /* 0C80; 0CFF; Kannada */
-            new UBInfo(0x0C80, 0x0CFF, "Kannada"), // Character.UnicodeBlock.KANNADA
-            /* 0D00; 0D7F; Malayalam */
-            new UBInfo(0x0D00, 0x0D7F, "Malayalam"), // Character.UnicodeBlock.MALAYALAM
-            /* 0D80; 0DFF; Sinhala */
-            new UBInfo(0x0D80, 0x0DFF, "Sinhala"), // Character.UnicodeBlock.SINHALA
-            /* 0E00; 0E7F; Thai */
-            new UBInfo(0x0E00, 0x0E7F, "Thai"), // Character.UnicodeBlock.THAI
-            /* 0E80; 0EFF; Lao */
-            new UBInfo(0x0E80, 0x0EFF, "Lao"), // Character.UnicodeBlock.LAO
-            /* 0F00; 0FFF; Tibetan */
-            new UBInfo(0x0F00, 0x0FFF, "Tibetan"), // Character.UnicodeBlock.TIBETAN
-            /* 1000; 109F; Myanmar */
-            new UBInfo(0x1000, 0x109F, "Myanmar"), // Character.UnicodeBlock.MYANMAR
-            /* 10A0; 10FF; Georgian */
-            new UBInfo(0x10A0, 0x10FF, "Georgian"), // Character.UnicodeBlock.GEORGIAN
-            /* 1100; 11FF; Hangul Jamo */
-            new UBInfo(0x1100, 0x11FF, "HangulJamo"), // Character.UnicodeBlock.HANGUL_JAMO
-            /* 1200; 137F; Ethiopic */
-            new UBInfo(0x1200, 0x137F, "Ethiopic"), // Character.UnicodeBlock.ETHIOPIC
-            /* 13A0; 13FF; Cherokee */
-            new UBInfo(0x13A0, 0x13FF, "Cherokee"), // Character.UnicodeBlock.CHEROKEE
-            /* 1400; 167F; Unified Canadian Aboriginal Syllabics */
-            new UBInfo(0x1400, 0x167F, "UnifiedCanadianAboriginalSyllabics"), // Character.UnicodeBlock.UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS
-            /* 1680; 169F; Ogham */
-            new UBInfo(0x1680, 0x169F, "Ogham"), // Character.UnicodeBlock.OGHAM
-            /* 16A0; 16FF; Runic */
-            new UBInfo(0x16A0, 0x16FF, "Runic"), // Character.UnicodeBlock.RUNIC
-            /* 1780; 17FF; Khmer */
-            new UBInfo(0x1780, 0x17FF, "Khmer"), // Character.UnicodeBlock.KHMER
-            /* 1800; 18AF; Mongolian */
-            new UBInfo(0x1800, 0x18AF, "Mongolian"), // Character.UnicodeBlock.MONGOLIAN
-            /* 1E00; 1EFF; Latin Extended Additional */
-            new UBInfo(0x1E00, 0x1EFF, "LatinExtendedAdditional"), // Character.UnicodeBlock.LATIN_EXTENDED_ADDITIONAL
-            /* 1F00; 1FFF; Greek Extended */
-            new UBInfo(0x1F00, 0x1FFF, "GreekExtended"), // Character.UnicodeBlock.GREEK_EXTENDED
-            /* 2000; 206F; General Punctuation */
-            new UBInfo(0x2000, 0x206F, "GeneralPunctuation"), // Character.UnicodeBlock.GENERAL_PUNCTUATION
-            /* 2070; 209F; Superscripts and Subscripts */
-            new UBInfo(0x2070, 0x209F, "SuperscriptsandSubscripts"), // Character.UnicodeBlock.SUPERSCRIPTS_AND_SUBSCRIPTS
-            /* 20A0; 20CF; Currency Symbols */
-            new UBInfo(0x20A0, 0x20CF, "CurrencySymbols"), // Character.UnicodeBlock.CURRENCY_SYMBOLS
-            /* 20D0; 20FF; Combining Marks for Symbols */
-            new UBInfo(0x20D0, 0x20FF, "CombiningMarksforSymbols"), // Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS
-            /* 2100; 214F; Letterlike Symbols */
-            new UBInfo(0x2100, 0x214F, "LetterlikeSymbols"), // Character.UnicodeBlock.LETTERLIKE_SYMBOLS
-            /* 2150; 218F; Number Forms */
-            new UBInfo(0x2150, 0x218F, "NumberForms"), // Character.UnicodeBlock.NUMBER_FORMS
-            /* 2190; 21FF; Arrows */
-            new UBInfo(0x2190, 0x21FF, "Arrows"), // Character.UnicodeBlock.ARROWS
-            /* 2200; 22FF; Mathematical Operators */
-            new UBInfo(0x2200, 0x22FF, "MathematicalOperators"), // Character.UnicodeBlock.MATHEMATICAL_OPERATORS
-            /* 2300; 23FF; Miscellaneous Technical */
-            new UBInfo(0x2300, 0x23FF, "MiscellaneousTechnical"), // Character.UnicodeBlock.MISCELLANEOUS_TECHNICAL
-            /* 2400; 243F; Control Pictures */
-            new UBInfo(0x2400, 0x243F, "ControlPictures"), // Character.UnicodeBlock.CONTROL_PICTURES
-            /* 2440; 245F; Optical Character Recognition */
-            new UBInfo(0x2440, 0x245F, "OpticalCharacterRecognition"), // Character.UnicodeBlock.OPTICAL_CHARACTER_RECOGNITION
-            /* 2460; 24FF; Enclosed Alphanumerics */
-            new UBInfo(0x2460, 0x24FF, "EnclosedAlphanumerics"), // Character.UnicodeBlock.ENCLOSED_ALPHANUMERICS
-            /* 2500; 257F; Box Drawing */
-            new UBInfo(0x2500, 0x257F, "BoxDrawing"), // Character.UnicodeBlock.BOX_DRAWING
-            /* 2580; 259F; Block Elements */
-            new UBInfo(0x2580, 0x259F, "BlockElements"), // Character.UnicodeBlock.BLOCK_ELEMENTS
-            /* 25A0; 25FF; Geometric Shapes */
-            new UBInfo(0x25A0, 0x25FF, "GeometricShapes"), // Character.UnicodeBlock.GEOMETRIC_SHAPES
-            /* 2600; 26FF; Miscellaneous Symbols */
-            new UBInfo(0x2600, 0x26FF, "MiscellaneousSymbols"), // Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS
-            /* 2700; 27BF; Dingbats */
-            new UBInfo(0x2700, 0x27BF, "Dingbats"), // Character.UnicodeBlock.DINGBATS
-            /* 2800; 28FF; Braille Patterns */
-            new UBInfo(0x2800, 0x28FF, "BraillePatterns"), // Character.UnicodeBlock.BRAILLE_PATTERNS
-            /* 2E80; 2EFF; CJK Radicals Supplement */
-            new UBInfo(0x2E80, 0x2EFF, "CJKRadicalsSupplement"), // Character.UnicodeBlock.CJK_RADICALS_SUPPLEMENT
-            /* 2F00; 2FDF; Kangxi Radicals */
-            new UBInfo(0x2F00, 0x2FDF, "KangxiRadicals"), // Character.UnicodeBlock.KANGXI_RADICALS
-            /* 2FF0; 2FFF; Ideographic Description Characters */
-            new UBInfo(0x2FF0, 0x2FFF, "IdeographicDescriptionCharacters"), // Character.UnicodeBlock.IDEOGRAPHIC_DESCRIPTION_CHARACTERS
-            /* 3000; 303F; CJK Symbols and Punctuation */
-            new UBInfo(0x3000, 0x303F, "CJKSymbolsandPunctuation"), // Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
-            /* 3040; 309F; Hiragana */
-            new UBInfo(0x3040, 0x309F, "Hiragana"), // Character.UnicodeBlock.HIRAGANA
-            /* 30A0; 30FF; Katakana */
-            new UBInfo(0x30A0, 0x30FF, "Katakana"), // Character.UnicodeBlock.KATAKANA
-            /* 3100; 312F; Bopomofo */
-            new UBInfo(0x3100, 0x312F, "Bopomofo"), // Character.UnicodeBlock.BOPOMOFO
-            /* 3130; 318F; Hangul Compatibility Jamo */
-            new UBInfo(0x3130, 0x318F, "HangulCompatibilityJamo"), // Character.UnicodeBlock.HANGUL_COMPATIBILITY_JAMO
-            /* 3190; 319F; Kanbun */
-            new UBInfo(0x3190, 0x319F, "Kanbun"), // Character.UnicodeBlock.KANBUN
-            /* 31A0; 31BF; Bopomofo Extended */
-            new UBInfo(0x31A0, 0x31BF, "BopomofoExtended"), // Character.UnicodeBlock.BOPOMOFO_EXTENDED
-            /* 3200; 32FF; Enclosed CJK Letters and Months */
-            new UBInfo(0x3200, 0x32FF, "EnclosedCJKLettersandMonths"), // Character.UnicodeBlock.ENCLOSED_CJK_LETTERS_AND_MONTHS
-            /* 3300; 33FF; CJK Compatibility */
-            new UBInfo(0x3300, 0x33FF, "CJKCompatibility"), // Character.UnicodeBlock.CJK_COMPATIBILITY
-            /* 3400; 4DB5; CJK Unified Ideographs Extension A */
-// BEGIN android-changed
-// Modified this to reflect current Unicode tables (or maybe it was a typo)
-            new UBInfo(0x3400, 0x4DBF, "CJKUnifiedIdeographsExtensionA"), // Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
-// END android-changed
-            /* 4E00; 9FFF; CJK Unified Ideographs */
-            new UBInfo(0x4E00, 0x9FFF, "CJKUnifiedIdeographs"), // Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
-            /* A000; A48F; Yi Syllables */
-            new UBInfo(0xA000, 0xA48F, "YiSyllables"), // Character.UnicodeBlock.YI_SYLLABLES
-            /* A490; A4CF; Yi Radicals */
-            new UBInfo(0xA490, 0xA4CF, "YiRadicals"), // Character.UnicodeBlock.YI_RADICALS
-            /* AC00; D7A3; Hangul Syllables */
-// BEGIN android-changed
-// Modified this to reflect current Unicode tables (or maybe it was a typo)
-            new UBInfo(0xAC00, 0xD7AF, "HangulSyllables"), // Character.UnicodeBlock.HANGUL_SYLLABLES
-// END android-changed
-            /* D800; DB7F; High Surrogates */
-            /* DB80; DBFF; High Private Use Surrogates */
-            /* DC00; DFFF; Low Surrogates */
-            /* E000; F8FF; Private Use */
-            /* F900; FAFF; CJK Compatibility Ideographs */
-            new UBInfo(0xF900, 0xFAFF, "CJKCompatibilityIdeographs"), // Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
-            /* FB00; FB4F; Alphabetic Presentation Forms */
-            new UBInfo(0xFB00, 0xFB4F, "AlphabeticPresentationForms"), // Character.UnicodeBlock.ALPHABETIC_PRESENTATION_FORMS
-            /* FB50; FDFF; Arabic Presentation Forms-A */
-            new UBInfo(0xFB50, 0xFDFF, "ArabicPresentationForms-A"), // Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_A
-            /* FE20; FE2F; Combining Half Marks */
-            new UBInfo(0xFE20, 0xFE2F, "CombiningHalfMarks"), // Character.UnicodeBlock.COMBINING_HALF_MARKS
-            /* FE30; FE4F; CJK Compatibility Forms */
-            new UBInfo(0xFE30, 0xFE4F, "CJKCompatibilityForms"), // Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
-            /* FE50; FE6F; Small Form Variants */
-            new UBInfo(0xFE50, 0xFE6F, "SmallFormVariants"), // Character.UnicodeBlock.SMALL_FORM_VARIANTS
-            /* FE70; FEFE; Arabic Presentation Forms-B */
-            // new UBInfo (0xFE70,0xFEFE,"InArabicPresentationForms-B"), //
-            // Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_B
-            /* FEFF; FEFF; Specials */
-// BEGIN android-changed
-// Modified this to reflect current Unicode tables (or maybe it was a typo)
-// FEFF is actually still Arabic Presentation Forms B
-//            new UBInfo(0xFEFF, 0xFEFF, "Specials"), // Character.UnicodeBlock.SPECIALS
-// END android-changed
-            /* FF00; FFEF; Halfwidth and Fullwidth Forms */
-            new UBInfo(0xFF00, 0xFFEF, "HalfwidthandFullwidthForms"), // Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
-            /* FFF0; FFFD; Specials */
-            // BEGIN android-changed
-// Modified this to reflect current Unicode tables (or maybe it was a typo)
-            new UBInfo(0xFFF0, 0xFFFF, "Specials") // Character.UnicodeBlock.SPECIALS
-// END android-changed
-    };
 }
diff --git a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternSyntaxExceptionTest.java b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternSyntaxExceptionTest.java
index d2d3596..0f9e1e6 100644
--- a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternSyntaxExceptionTest.java
+++ b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternSyntaxExceptionTest.java
@@ -16,70 +16,130 @@
 
 package org.apache.harmony.regex.tests.java.util.regex;
 
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
 import junit.framework.TestCase;
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
 
 public class PatternSyntaxExceptionTest extends TestCase {
+  public void testPatternSyntaxException() {
+    // Normal case
+    PatternSyntaxException e = new PatternSyntaxException("Foo", "Bar", 0);
+    assertEquals("Foo", e.getDescription());
+    assertEquals("Bar", e.getPattern());
+    assertEquals(0, e.getIndex());
 
-    public void testPatternSyntaxException() {
-        // Normal case
-        PatternSyntaxException e = new PatternSyntaxException("Foo", "Bar", 0);
-        assertEquals("Foo", e.getDescription());
-        assertEquals("Bar", e.getPattern());
-        assertEquals(0, e.getIndex());
+    String s = e.getMessage();
+    assertTrue(s.contains("Foo"));
+    assertTrue(s.contains("Bar"));
+    assertTrue(s.contains("0"));
 
-        String s = e.getMessage();
-        assertTrue(s.contains("Foo"));
-        assertTrue(s.contains("Bar"));
-        assertTrue(s.contains("0"));
+    // No description specified
+    e = new PatternSyntaxException(null, "Bar", 0);
+    assertEquals(null, e.getDescription());
+    assertEquals("Bar", e.getPattern());
+    assertEquals(0, e.getIndex());
 
-        // No description specified
-        e = new PatternSyntaxException(null, "Bar", 0);
-        assertEquals(null, e.getDescription());
-        assertEquals("Bar", e.getPattern());
-        assertEquals(0, e.getIndex());
+    s = e.getMessage();
+    assertFalse(s.contains("Foo"));
+    assertTrue(s.contains("Bar"));
+    assertTrue(s.contains("0"));
 
-        s = e.getMessage();
-        assertFalse(s.contains("Foo"));
-        assertTrue(s.contains("Bar"));
-        assertTrue(s.contains("0"));
+    // No pattern specified
+    e = new PatternSyntaxException("Foo", null, 0);
+    assertEquals("Foo", e.getDescription());
+    assertEquals(null, e.getPattern());
+    assertEquals(0, e.getIndex());
 
-        // No pattern specified
-        e = new PatternSyntaxException("Foo", null, 0);
-        assertEquals("Foo", e.getDescription());
-        assertEquals(null, e.getPattern());
-        assertEquals(0, e.getIndex());
+    s = e.getMessage();
+    assertTrue(s.contains("Foo"));
+    assertFalse(s.contains("Bar"));
+    assertTrue(s.contains("0"));
 
-        s = e.getMessage();
-        assertTrue(s.contains("Foo"));
-        assertFalse(s.contains("Bar"));
-        assertTrue(s.contains("0"));
+    // Neither description nor pattern specified
+    e = new PatternSyntaxException(null, null, 0);
+    assertEquals(null, e.getDescription());
+    assertEquals(null, e.getPattern());
+    assertEquals(0, e.getIndex());
 
-        // Neither description nor pattern specified
-        e = new PatternSyntaxException(null, null, 0);
-        assertEquals(null, e.getDescription());
-        assertEquals(null, e.getPattern());
-        assertEquals(0, e.getIndex());
+    s = e.getMessage();
+    assertFalse(s.contains("Foo"));
+    assertFalse(s.contains("Bar"));
+    assertTrue(s.contains("0"));
 
-        s = e.getMessage();
-        assertFalse(s.contains("Foo"));
-        assertFalse(s.contains("Bar"));
-        assertTrue(s.contains("0"));
+    // No index specified
+    e = new PatternSyntaxException("Foo", "Bar", -1);
+    assertEquals(-1, e.getIndex());
 
-        // No index specified
-        e = new PatternSyntaxException("Foo", "Bar", -1);
-        assertEquals(-1, e.getIndex());
+    s = e.getMessage();
+    assertFalse(s.contains("^"));
 
-        s = e.getMessage();
-        assertFalse(s.contains("^"));
+    // No pattern, but index specified
+    e = new PatternSyntaxException("Foo", null, 0);
+    assertEquals(0, e.getIndex());
 
-        // No pattern, but index specified
-        e = new PatternSyntaxException("Foo", null, 0);
-        assertEquals(0, e.getIndex());
+    s = e.getMessage();
+    assertFalse(s.contains("^"));
+  }
 
-        s = e.getMessage();
-        assertFalse(s.contains("^"));
+  public void testCase() {
+    String regex = "(";
+    try {
+      Pattern.compile(regex);
+      fail("PatternSyntaxException expected");
+    } catch (PatternSyntaxException e) {
+      assertEquals(1, e.getIndex());
+      assertEquals(regex, e.getPattern());
     }
+  }
 
+  public void testCase2() {
+    String regex = "[4-";
+    try {
+      Pattern.compile(regex);
+      fail("PatternSyntaxException expected");
+    } catch (PatternSyntaxException e) {
+      assertEquals(3, e.getIndex());
+      assertEquals(regex, e.getPattern());
+    }
+  }
+
+  // Regression test for HARMONY-3787
+  public void test_objectStreamField() {
+    ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(PatternSyntaxException.class);
+    assertNotNull(objectStreamClass.getField("desc"));
+  }
+
+  public void testSerializationCompatibility() throws Exception {
+    PatternSyntaxException object = new PatternSyntaxException("TESTDESC", "TESTREGEX", 3);
+    SerializationTest.verifyGolden(this, object, PATTERNSYNTAXEXCEPTION_COMPARATOR);
+  }
+
+  public void testSerializationSelf() throws Exception {
+    PatternSyntaxException object = new PatternSyntaxException("TESTDESC", "TESTREGEX", 3);
+    SerializationTest.verifySelf(object, PATTERNSYNTAXEXCEPTION_COMPARATOR);
+  }
+
+  private static final SerializableAssert PATTERNSYNTAXEXCEPTION_COMPARATOR = new SerializableAssert() {
+    public void assertDeserialized(Serializable initial, Serializable deserialized) {
+
+      // do common checks for all throwable objects
+      SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial, deserialized);
+
+      PatternSyntaxException initPatternSyntaxException = (PatternSyntaxException) initial;
+      PatternSyntaxException dserPatternSyntaxException = (PatternSyntaxException) deserialized;
+
+      // verify fields
+      assertEquals(initPatternSyntaxException.getDescription(),
+                   dserPatternSyntaxException.getDescription());
+      assertEquals(initPatternSyntaxException.getPattern(),
+                   dserPatternSyntaxException.getPattern());
+      assertEquals(initPatternSyntaxException.getIndex(),
+                   dserPatternSyntaxException.getIndex());
+    }
+  };
 }
diff --git a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java
index a81d294..a4f534b 100644
--- a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java
+++ b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java
@@ -76,7 +76,7 @@
         assertNotSame(p.matcher("a"), p.matcher("a"));
     }
 
-    public void testSplitCharSequenceint() {
+    public void testSplitCharSequenceInt() {
         // splitting CharSequence which ends with pattern
         // bug6193
         assertEquals(",,".split(",", 3).length, 3);
@@ -414,7 +414,7 @@
         }
     }
 
-    public void testCompileStringint() {
+    public void testCompileStringInt() {
         /*
          * these tests are needed to verify that appropriate exceptions are
          * thrown
@@ -455,6 +455,7 @@
 
         /*
          * This pattern should compile - HARMONY-2127
+         * icu4c doesn't support canonical equivalence.
          */
 //        pattern = "x(?c)y";
 //        Pattern.compile(pattern);
@@ -628,10 +629,28 @@
         assertTrue(mat.matches());
     }
 
-    public void testBug181() {
+    public void test_bug_181() {
         Pattern.compile("[\\t-\\r]");
     }
 
+    // https://code.google.com/p/android/issues/detail?id=40103
+    public void test_bug_40103() {
+        Pattern.compile("(?<!abc {1,100}|def {1,100}|ghi {1,100})jkl");
+
+        // Looks like harmony had a similar "Bug187"...
+        Pattern.compile("|(?idmsux-idmsux)|(?idmsux-idmsux)|[^|\\[-\\0274|\\,-\\\\[^|W\\}\\nq\\x65\\002\\xFE\\05\\06\\00\\x66\\x47i\\,\\xF2\\=\\06\\u0EA4\\x9B\\x3C\\f\\|\\{\\xE5\\05\\r\\u944A\\xCA\\e|\\x19\\04\\x07\\04\\u607B\\023\\0073\\x91Tr\\0150\\x83]]?(?idmsux-idmsux:\\p{Alpha}{7}?)||(?<=[^\\uEC47\\01\\02\\u3421\\a\\f\\a\\013q\\035w\\e])(?<=\\p{Punct}{0,}?)(?=^\\p{Lower})(?!\\b{8,14})(?<![|\\00-\\0146[^|\\04\\01\\04\\060\\f\\u224DO\\x1A\\xC4\\00\\02\\0315\\0351\\u84A8\\xCBt\\xCC\\06|\\0141\\00\\=\\e\\f\\x6B\\0026Tb\\040\\x76xJ&&[\\\\-\\]\\05\\07\\02\\u2DAF\\t\\x9C\\e\\0023\\02\\,X\\e|\\u6058flY\\u954C]]]{5}?)(?<=\\p{Sc}{8}+)[^|\\026-\\u89BA|o\\u6277\\t\\07\\x50&&\\p{Punct}]{8,14}+((?<=^\\p{Punct})|(?idmsux-idmsux)||(?>[\\x3E-\\]])|(?idmsux-idmsux:\\p{Punct})|(?<![\\0111\\0371\\xDF\\u6A49\\07\\u2A4D\\00\\0212\\02Xd-\\xED[^\\a-\\0061|\\0257\\04\\f\\[\\0266\\043\\03\\x2D\\042&&[^\\f-\\]&&\\s]]])|(?>[|\\n\\042\\uB09F\\06\\u0F2B\\uC96D\\x89\\uC166\\xAA|\\04-\\][^|\\a\\|\\rx\\04\\uA770\\n\\02\\t\\052\\056\\0274\\|\\=\\07\\e|\\00-\\x1D&&[^\\005\\uB15B\\uCDAC\\n\\x74\\0103\\0147\\uD91B\\n\\062G\\u9B4B\\077\\}\\0324&&[^\\0302\\,\\0221\\04\\u6D16\\04xy\\uD193\\[\\061\\06\\045\\x0F|\\e\\xBB\\f\\u1B52\\023\\u3AD2\\033\\007\\022\\}\\x66\\uA63FJ-\\0304]]]]{0,0})||(?<![^|\\0154U\\u0877\\03\\fy\\n\\|\\0147\\07-\\=[|q\\u69BE\\0243\\rp\\053\\02\\x33I\\u5E39\\u9C40\\052-\\xBC[|\\0064-\\?|\\uFC0C\\x30\\0060\\x45\\\\\\02\\?p\\xD8\\0155\\07\\0367\\04\\uF07B\\000J[^|\\0051-\\{|\\u9E4E\\u7328\\]\\u6AB8\\06\\x71\\a\\]\\e\\|KN\\u06AA\\0000\\063\\u2523&&[\\005\\0277\\x41U\\034\\}R\\u14C7\\u4767\\x09\\n\\054Ev\\0144\\<\\f\\,Q-\\xE4]]]]]{3}+)|(?>^+)|(?![^|\\|\\nJ\\t\\<\\04E\\\\\\t\\01\\\\\\02\\|\\=\\}\\xF3\\uBEC2\\032K\\014\\uCC5F\\072q\\|\\0153\\xD9\\0322\\uC6C8[^\\t\\0342\\x34\\x91\\06\\{\\xF1\\a\\u1710\\?\\xE7\\uC106\\02pF\\<&&[^|\\]\\064\\u381D\\u50CF\\eO&&[^|\\06\\x2F\\04\\045\\032\\u8536W\\0377\\0017|\\x06\\uE5FA\\05\\xD4\\020\\04c\\xFC\\02H\\x0A\\r]]]]+?)(?idmsux-idmsux)|(?<![|\\r-\\,&&[I\\t\\r\\0201\\xDB\\e&&[^|\\02\\06\\00\\<\\a\\u7952\\064\\051\\073\\x41\\?n\\040\\0053\\031&&[\\x15-\\|]]]]{8,11}?)(?![^|\\<-\\uA74B\\xFA\\u7CD2\\024\\07n\\<\\x6A\\0042\\uE4FF\\r\\u896B\\[\\=\\042Y&&^\\p{ASCII}]++)|(?<![R-\\|&&[\\a\\0120A\\u6145\\<\\050-d[|\\e-\\uA07C|\\016-\\u80D9]]]{1,}+)|(?idmsux-idmsux)|(?idmsux-idmsux)|(?idmsux-idmsux:\\B{6,}?)|(?<=\\D{5,8}?)|(?>[\\{-\\0207|\\06-\\0276\\p{XDigit}])(?idmsux-idmsux:[^|\\x52\\0012\\]u\\xAD\\0051f\\0142\\\\l\\|\\050\\05\\f\\t\\u7B91\\r\\u7763\\{|h\\0104\\a\\f\\0234\\u2D4F&&^\\P{InGreek}]))");
+    }
+
+    public void test_bug_4472() {
+        // HARMONY-4472
+        Pattern.compile("a*.+");
+    }
+
+    public void test_bug_5858() {
+        // HARMONY-5858
+        Pattern.compile("\\u6211", Pattern.LITERAL);
+    }
+
     public void testOrphanQuantifiers() {
         try {
             Pattern.compile("+++++");
@@ -682,13 +701,13 @@
         String IPV4_REGEXP_STR = "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$";
         String HOSTNAME_REGEXP_STR = "\\w+[\\w\\-\\.]*";
 
-        Pattern URI_REGEXP = Pattern.compile(URI_REGEXP_STR);
-        Pattern REL_URI_REGEXP = Pattern.compile(REL_URI_REGEXP_STR);
-        Pattern SCHEME_REGEXP = Pattern.compile(SCHEME_REGEXP_STR);
-        Pattern IPV4_REGEXP = Pattern.compile(IPV4_REGEXP_STR);
-        Pattern IPV6_REGEXP = Pattern.compile(IPV6_REGEXP_STR);
-        Pattern IPV6_REGEXP2 = Pattern.compile(IPV6_REGEXP_STR2);
-        Pattern HOSTNAME_REGEXP = Pattern.compile(HOSTNAME_REGEXP_STR);
+        Pattern.compile(URI_REGEXP_STR);
+        Pattern.compile(REL_URI_REGEXP_STR);
+        Pattern.compile(SCHEME_REGEXP_STR);
+        Pattern.compile(IPV4_REGEXP_STR);
+        Pattern.compile(IPV6_REGEXP_STR);
+        Pattern.compile(IPV6_REGEXP_STR2);
+        Pattern.compile(HOSTNAME_REGEXP_STR);
     }
 
     public void testFindBoundaryCases1() {
@@ -739,16 +758,15 @@
         Pattern pat = Pattern.compile(".*");
         Matcher mat = pat.matcher("\na\n");
         int k = 0;
-
         for (; mat.find(); k++) {
             assertEquals(res[k], mat.group());
         }
+        assertEquals(4, k);
     }
 
     public void testBackReferences() {
         Pattern pat = Pattern.compile("(\\((\\w*):(.*):(\\2)\\))");
-        Matcher mat = pat
-                .matcher("(start1: word :start1)(start2: word :start2)");
+        Matcher mat = pat.matcher("(start1: word :start1)(start2: word :start2)");
         int k = 1;
         for (; mat.find(); k++) {
             assertEquals("start" + k, mat.group(2));
@@ -813,7 +831,6 @@
 
     public void testEmptyFamily() {
         Pattern.compile("\\p{Lower}");
-        String a = "*";
     }
 
     public void testNonCaptConstr() {
@@ -886,21 +903,21 @@
     }
 
     public void testCorrectReplacementBackreferencedJointSet() {
-        Pattern pat = Pattern.compile("ab(a)*\\1");
-        pat = Pattern.compile("abc(cd)fg");
-        pat = Pattern.compile("aba*cd");
-        pat = Pattern.compile("ab(a)*+cd");
-        pat = Pattern.compile("ab(a)*?cd");
-        pat = Pattern.compile("ab(a)+cd");
-        pat = Pattern.compile(".*(.)\\1");
-        pat = Pattern.compile("ab((a)|c|d)e");
-        pat = Pattern.compile("abc((a(b))cd)");
-        pat = Pattern.compile("ab(a)++cd");
-        pat = Pattern.compile("ab(a)?(c)d");
-        pat = Pattern.compile("ab(a)?+cd");
-        pat = Pattern.compile("ab(a)??cd");
-        pat = Pattern.compile("ab(a)??cd");
-        pat = Pattern.compile("ab(a){1,3}?(c)d");
+        Pattern.compile("ab(a)*\\1");
+        Pattern.compile("abc(cd)fg");
+        Pattern.compile("aba*cd");
+        Pattern.compile("ab(a)*+cd");
+        Pattern.compile("ab(a)*?cd");
+        Pattern.compile("ab(a)+cd");
+        Pattern.compile(".*(.)\\1");
+        Pattern.compile("ab((a)|c|d)e");
+        Pattern.compile("abc((a(b))cd)");
+        Pattern.compile("ab(a)++cd");
+        Pattern.compile("ab(a)?(c)d");
+        Pattern.compile("ab(a)?+cd");
+        Pattern.compile("ab(a)??cd");
+        Pattern.compile("ab(a)??cd");
+        Pattern.compile("ab(a){1,3}?(c)d");
     }
 
     public void testCompilePatternWithTerminatorMark() {
@@ -1020,24 +1037,6 @@
         assertTrue(mat.matches());
     }
 
-    public void testCompileNonCaptGroup() {
-        boolean isCompiled = false;
-
-        try {
-// BEGIN android-change
-// We don't have canonical equivalence.
-            Pattern pat = Pattern.compile("(?:)");
-            pat = Pattern.compile("(?:)", Pattern.DOTALL);
-            pat = Pattern.compile("(?:)", Pattern.CASE_INSENSITIVE);
-            pat = Pattern.compile("(?:)", Pattern.COMMENTS | Pattern.UNIX_LINES);
-// END android-change
-            isCompiled = true;
-        } catch (PatternSyntaxException e) {
-            System.out.println(e);
-        }
-        assertTrue(isCompiled);
-    }
-
     public void testEmbeddedFlags() {
         String baseString = "(?i)((?s)a)";
         String testString = "A";
@@ -1071,15 +1070,7 @@
     }
 
     public void testAltWithFlags() {
-        boolean isCompiled = false;
-
-        try {
-            Pattern pat = Pattern.compile("|(?i-xi)|()");
-            isCompiled = true;
-        } catch (PatternSyntaxException e) {
-            System.out.println(e);
-        }
-        assertTrue(isCompiled);
+        Pattern.compile("|(?i-xi)|()");
     }
 
     public void testRestoreFlagsAfterGroup() {
@@ -1146,276 +1137,6 @@
         assertNotNull(pattern);
     }
 
-    /**
-     * s original test was fixed to pass on RI
-     */
-
-// BEGIN android-removed
-// We don't have canonical equivalence.
-//    public void testCanonEqFlag() {
-//
-//        /*
-//         * for decompositions see
-//         * http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt
-//         * http://www.unicode.org/reports/tr15/#Decomposition
-//         */
-//        String baseString;
-//        String testString;
-//        Pattern pat;
-//        Matcher mat;
-//
-//        baseString = "ab(a*)\\1";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-//        baseString = "a(abcdf)d";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-//        baseString = "aabcdfd";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-//        // \u01E0 -> \u0226\u0304 ->\u0041\u0307\u0304
-//        // \u00CC -> \u0049\u0300
-//
-//        /*
-//         * baseString = "\u01E0\u00CCcdb(ac)"; testString =
-//         * "\u0226\u0304\u0049\u0300cdbac"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         */
-//        baseString = "\u01E0cdb(a\u00CCc)";
-//        testString = "\u0041\u0307\u0304cdba\u0049\u0300c";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher(testString);
-//        assertTrue(mat.matches());
-//
-//        baseString = "a\u00CC";
-//        testString = "a\u0049\u0300";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher(testString);
-//        assertTrue(mat.matches());
-//
-//        /*
-//         * baseString = "\u0226\u0304cdb(ac\u0049\u0300)"; testString =
-//         * "\u01E0cdbac\u00CC"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         *
-//         * baseString = "cdb(?:\u0041\u0307\u0304\u00CC)"; testString =
-//         * "cdb\u0226\u0304\u0049\u0300"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         *
-//         * baseString = "\u01E0[a-c]\u0049\u0300cdb(ac)"; testString =
-//         * "\u01E0b\u00CCcdbac"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         *
-//         * baseString = "\u01E0|\u00CCcdb(ac)"; testString =
-//         * "\u0041\u0307\u0304"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         *
-//         * baseString = "\u00CC?cdb(ac)*(\u01E0)*[a-c]"; testString =
-//         * "cdb\u0041\u0307\u0304b"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         */
-//        baseString = "a\u0300";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher("a\u00E0a");
-//        assertTrue(mat.find());
-//
-//        /*
-//         * baseString = "\u7B20\uF9F8abc"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher("\uF9F8\uF9F8abc");
-//         * assertTrue(mat.matches());
-//         *
-//         * //\u01F9 -> \u006E\u0300 //\u00C3 -> \u0041\u0303
-//         *
-//         * baseString = "cdb(?:\u00C3\u006E\u0300)"; testString =
-//         * "cdb\u0041\u0303\u01F9"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         *
-//         * //\u014C -> \u004F\u0304 //\u0163 -> \u0074\u0327
-//         *
-//         * baseString = "cdb(?:\u0163\u004F\u0304)"; testString =
-//         * "cdb\u0074\u0327\u014C"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         */
-//        // \u00E1->a\u0301
-//        // canonical ordering takes place \u0301\u0327 -> \u0327\u0301
-//        baseString = "c\u0327\u0301";
-//        testString = "c\u0301\u0327";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher(testString);
-//        assertTrue(mat.matches());
-//
-//        /*
-//         * Hangul decompositions
-//         */
-//        // \uD4DB->\u1111\u1171\u11B6
-//        // \uD21E->\u1110\u116D\u11B5
-//        // \uD264->\u1110\u1170
-//        // not Hangul:\u0453->\u0433\u0301
-//        baseString = "a\uD4DB\u1111\u1171\u11B6\uD264";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-//        baseString = "\u0453c\uD4DB";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-//        baseString = "a\u1110\u116D\u11B5b\uD21Ebc";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-//        /*
-//         * baseString = "\uD4DB\uD21E\u1110\u1170cdb(ac)"; testString =
-//         * "\u1111\u1171\u11B6\u1110\u116D\u11B5\uD264cdbac"; pat =
-//         * Pattern.compile(baseString, Pattern.CANON_EQ); mat =
-//         * pat.matcher(testString); assertTrue(mat.matches());
-//         */
-//        baseString = "\uD4DB\uD264cdb(a\uD21Ec)";
-//        testString = "\u1111\u1171\u11B6\u1110\u1170cdba\u1110\u116D\u11B5c";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher(testString);
-//        assertTrue(mat.matches());
-//
-//        baseString = "a\uD4DB";
-//        testString = "a\u1111\u1171\u11B6";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher(testString);
-//        assertTrue(mat.matches());
-//
-//        baseString = "a\uD21E";
-//        testString = "a\u1110\u116D\u11B5";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher(testString);
-//        assertTrue(mat.matches());
-//
-//        /*
-//         * baseString = "\u1111\u1171\u11B6cdb(ac\u1110\u116D\u11B5)";
-//         * testString = "\uD4DBcdbac\uD21E"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         *
-//         * baseString = "cdb(?:\u1111\u1171\u11B6\uD21E)"; testString =
-//         * "cdb\uD4DB\u1110\u116D\u11B5"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         *
-//         * baseString = "\uD4DB[a-c]\u1110\u116D\u11B5cdb(ac)"; testString =
-//         * "\uD4DBb\uD21Ecdbac"; pat = Pattern.compile(baseString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         */
-//        baseString = "\uD4DB|\u00CCcdb(ac)";
-//        testString = "\u1111\u1171\u11B6";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher(testString);
-//        assertTrue(mat.matches());
-//
-//        baseString = "\uD4DB|\u00CCcdb(ac)";
-//        testString = "\u1111\u1171";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher(testString);
-//        assertFalse(mat.matches());
-//
-//        baseString = "\u00CC?cdb(ac)*(\uD4DB)*[a-c]";
-//        testString = "cdb\u1111\u1171\u11B6b";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher(testString);
-//        assertTrue(mat.matches());
-//
-//        baseString = "\uD4DB";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher("a\u1111\u1171\u11B6a");
-//        assertTrue(mat.find());
-//
-//        baseString = "\u1111";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher("bcda\uD4DBr");
-//        assertFalse(mat.find());
-//    }
-//
-//    /**
-//     * s original test was fixed to pass on RI
-//     */
-//
-//    public void testIndexesCanonicalEq() {
-//        String baseString;
-//        String testString;
-//        Pattern pat;
-//        Matcher mat;
-//
-//        baseString = "\uD4DB";
-//        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//        mat = pat.matcher("bcda\u1111\u1171\u11B6awr");
-//        assertTrue(mat.find());
-//        assertEquals(mat.start(), 4);
-//        assertEquals(mat.end(), 7);
-//
-//        /*
-//         * baseString = "\uD4DB\u1111\u1171\u11B6"; pat =
-//         * Pattern.compile(baseString, Pattern.CANON_EQ); mat =
-//         * pat.matcher("bcda\u1111\u1171\u11B6\uD4DBawr");
-//         * assertTrue(mat.find()); assertEquals(mat.start(), 4);
-//         * assertEquals(mat.end(), 8);
-//         *
-//         * baseString = "\uD4DB\uD21E\u1110\u1170"; testString =
-//         * "abcabc\u1111\u1171\u11B6\u1110\u116D\u11B5\uD264cdbac"; pat =
-//         * Pattern.compile(baseString, Pattern.CANON_EQ); mat =
-//         * pat.matcher(testString); assertTrue(mat.find());
-//         * assertEquals(mat.start(), 6); assertEquals(mat.end(), 13);
-//         */}
-//
-//    /**
-//     * s original test was fixed to pass on RI
-//     */
-//
-//    public void testCanonEqFlagWithSupplementaryCharacters() {
-//
-//        /*
-//         * \u1D1BF->\u1D1BB\u1D16F->\u1D1B9\u1D165\u1D16F in UTF32
-//         * \uD834\uDDBF->\uD834\uDDBB\uD834\uDD6F
-//         * ->\uD834\uDDB9\uD834\uDD65\uD834\uDD6F in UTF16
-//         */
-//        String patString = "abc\uD834\uDDBFef";
-//        String testString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef";
-//        Pattern pat = Pattern.compile(patString, Pattern.CANON_EQ);
-//        Matcher mat = pat.matcher(testString);
-//        assertTrue(mat.matches());
-//        /*
-//         * testString = "abc\uD834\uDDBB\uD834\uDD6Fef"; mat =
-//         * pat.matcher(testString); assertTrue(mat.matches());
-//         *
-//         * patString = "abc\uD834\uDDBB\uD834\uDD6Fef"; testString =
-//         * "abc\uD834\uDDBFef"; pat = Pattern.compile(patString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         */
-//        testString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef";
-//        mat = pat.matcher(testString);
-//        assertTrue(mat.matches());
-//        /*
-//         * patString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef"; testString =
-//         * "abc\uD834\uDDBFef"; pat = Pattern.compile(patString,
-//         * Pattern.CANON_EQ); mat = pat.matcher(testString);
-//         * assertTrue(mat.matches());
-//         *
-//         * testString = "abc\uD834\uDDBB\uD834\uDD6Fef"; mat =
-//         * pat.matcher(testString); assertTrue(mat.matches());
-//         */
-//        /*
-//         * testSupplementary characters with no decomposition
-//         */
-//        /*
-//         * patString = "a\uD9A0\uDE8Ebc\uD834\uDDBB\uD834\uDD6Fe\uDE8Ef";
-//         * testString = "a\uD9A0\uDE8Ebc\uD834\uDDBFe\uDE8Ef"; pat =
-//         * Pattern.compile(patString, Pattern.CANON_EQ); mat =
-//         * pat.matcher(testString); assertTrue(mat.matches());
-//         */}
-// END android-removed
-
     public void testRangesWithSurrogatesSupplementary() {
         String patString = "[abc\uD8D2]";
         String testString = "\uD8D2";
@@ -1493,6 +1214,7 @@
 // might want to duplicate.
 //        assertFalse(mat.find());
 // END android-changed
+
         testString = "abcd\uD8D3abc";
         mat = pat.matcher(testString);
         assertTrue(mat.find());
@@ -1781,4 +1503,341 @@
         boolean isPartialMatch = !m.matches() && m.hitEnd();
         assertFalse(isPartialMatch);
     }
+
+    public void testCommentsInPattern() {
+        Pattern p = Pattern.compile("ab# this is a comment\ncd", Pattern.COMMENTS);
+        assertTrue(p.matcher("abcd").matches());
+    }
+
+    public void testCompileNonCaptGroup() {
+        // icu4c doesn't support CANON_EQ.
+        Pattern.compile("(?:)"/*, Pattern.CANON_EQ*/);
+        Pattern.compile("(?:)", /*Pattern.CANON_EQ |*/ Pattern.DOTALL);
+        Pattern.compile("(?:)", /*Pattern.CANON_EQ |*/ Pattern.CASE_INSENSITIVE);
+        Pattern.compile("(?:)", /*Pattern.CANON_EQ |*/ Pattern.COMMENTS | Pattern.UNIX_LINES);
+    }
+
+    public void testFlagsMethod() {
+        // icu4c doesn't count inline flags that span the entire regex as being global flags.
+        // Android just returns those flags actually passed to Pattern.compile.
+        if (true) {
+            return;
+        }
+
+        String baseString;
+        Pattern pat;
+
+        // These tests are for compatibility with RI only. Logically we have to
+        // return only flags specified during the compilation. For example
+        // pat.flags() == 0 when we compile Pattern pat =
+        // Pattern.compile("(?i)abc(?-i)"); but the whole expression is compiled
+        // in a case insensitive manner. So there is little sense to do calls to
+        // flags() now.
+        baseString = "(?-i)";
+        pat = Pattern.compile(baseString);
+
+        baseString = "(?idmsux)abc(?-i)vg(?-dmu)";
+        pat = Pattern.compile(baseString);
+        assertEquals(pat.flags(), Pattern.DOTALL | Pattern.COMMENTS);
+
+        baseString = "(?idmsux)abc|(?-i)vg|(?-dmu)";
+        pat = Pattern.compile(baseString);
+        assertEquals(pat.flags(), Pattern.DOTALL | Pattern.COMMENTS);
+
+        baseString = "(?is)a((?x)b.)";
+        pat = Pattern.compile(baseString);
+        assertEquals(pat.flags(), Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
+
+        baseString = "(?i)a((?-i))";
+        pat = Pattern.compile(baseString);
+        assertEquals(pat.flags(), Pattern.CASE_INSENSITIVE);
+
+        baseString = "((?i)a)";
+        pat = Pattern.compile(baseString);
+        assertEquals(pat.flags(), 0);
+
+        pat = Pattern.compile("(?is)abc");
+        assertEquals(pat.flags(), Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
+    }
+
+    public void testCanonEqFlag() {
+        // icu4c doesn't support CANON_EQ.
+        if (true) {
+            return;
+        }
+
+        // for decompositions see
+        // http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt
+        // http://www.unicode.org/reports/tr15/#Decomposition
+        String baseString;
+        String testString;
+        Pattern pat;
+        Matcher mat;
+
+        baseString = "ab(a*)\\1";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+        baseString = "a(abcdf)d";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+        baseString = "aabcdfd";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+        // \u01E0 -> \u0226\u0304 ->\u0041\u0307\u0304
+        // \u00CC -> \u0049\u0300
+
+        baseString = "\u01E0\u00CCcdb(ac)";
+        testString = "\u0226\u0304\u0049\u0300cdbac";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\u01E0cdb(a\u00CCc)";
+        testString = "\u0041\u0307\u0304cdba\u0049\u0300c";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "a\u00CC";
+        testString = "a\u0049\u0300";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\u0226\u0304cdb(ac\u0049\u0300)";
+        testString = "\u01E0cdbac\u00CC";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "cdb(?:\u0041\u0307\u0304\u00CC)";
+        testString = "cdb\u0226\u0304\u0049\u0300";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\u01E0[a-c]\u0049\u0300cdb(ac)";
+        testString = "\u01E0b\u00CCcdbac";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\u01E0|\u00CCcdb(ac)";
+        testString = "\u0041\u0307\u0304";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\u00CC?cdb(ac)*(\u01E0)*[a-c]";
+        testString = "cdb\u0041\u0307\u0304b";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "a\u0300";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher("a\u00E0a");
+        assertTrue(mat.find());
+
+        baseString = "\u7B20\uF9F8abc";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher("\uF9F8\uF9F8abc");
+        assertTrue(mat.matches());
+
+        // \u01F9 -> \u006E\u0300
+        // \u00C3 -> \u0041\u0303
+
+        baseString = "cdb(?:\u00C3\u006E\u0300)";
+        testString = "cdb\u0041\u0303\u01F9";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        // \u014C -> \u004F\u0304
+        // \u0163 -> \u0074\u0327
+
+        baseString = "cdb(?:\u0163\u004F\u0304)";
+        testString = "cdb\u0074\u0327\u014C";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        // \u00E1->a\u0301
+        // canonical ordering takes place \u0301\u0327 -> \u0327\u0301
+
+        baseString = "c\u0327\u0301";
+        testString = "c\u0301\u0327";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        /*
+        Hangul decompositions
+        */
+        // \uD4DB->\u1111\u1171\u11B6
+        // \uD21E->\u1110\u116D\u11B5
+        // \uD264->\u1110\u1170
+        // not Hangul:\u0453->\u0433\u0301
+        baseString = "a\uD4DB\u1111\u1171\u11B6\uD264";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+        baseString = "\u0453c\uD4DB";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+        baseString = "a\u1110\u116D\u11B5b\uD21Ebc";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+        baseString = "\uD4DB\uD21E\u1110\u1170cdb(ac)";
+        testString = "\u1111\u1171\u11B6\u1110\u116D\u11B5\uD264cdbac";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\uD4DB\uD264cdb(a\uD21Ec)";
+        testString = "\u1111\u1171\u11B6\u1110\u1170cdba\u1110\u116D\u11B5c";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "a\uD4DB";
+        testString = "a\u1111\u1171\u11B6";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "a\uD21E";
+        testString = "a\u1110\u116D\u11B5";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\u1111\u1171\u11B6cdb(ac\u1110\u116D\u11B5)";
+        testString = "\uD4DBcdbac\uD21E";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "cdb(?:\u1111\u1171\u11B6\uD21E)";
+        testString = "cdb\uD4DB\u1110\u116D\u11B5";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\uD4DB[a-c]\u1110\u116D\u11B5cdb(ac)";
+        testString = "\uD4DBb\uD21Ecdbac";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\uD4DB|\u00CCcdb(ac)";
+        testString = "\u1111\u1171\u11B6";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\uD4DB|\u00CCcdb(ac)";
+        testString = "\u1111\u1171";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertFalse(mat.matches());
+
+        baseString = "\u00CC?cdb(ac)*(\uD4DB)*[a-c]";
+        testString = "cdb\u1111\u1171\u11B6b";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        baseString = "\uD4DB";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher("a\u1111\u1171\u11B6a");
+        assertTrue(mat.find());
+
+        baseString = "\u1111";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher("bcda\uD4DBr");
+        assertFalse(mat.find());
+    }
+
+    public void testIndexesCanonicalEq() {
+        // icu4c doesn't support CANON_EQ.
+        if (true) {
+            return;
+        }
+
+        String baseString;
+        String testString;
+        Pattern pat;
+        Matcher mat;
+
+        baseString = "\uD4DB";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher("bcda\u1111\u1171\u11B6awr");
+        assertTrue(mat.find());
+        assertEquals(mat.start(), 4);
+        assertEquals(mat.end(), 7);
+
+        baseString = "\uD4DB\u1111\u1171\u11B6";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher("bcda\u1111\u1171\u11B6\uD4DBawr");
+        assertTrue(mat.find());
+        assertEquals(mat.start(), 4);
+        assertEquals(mat.end(), 8);
+
+        baseString = "\uD4DB\uD21E\u1110\u1170";
+        testString = "abcabc\u1111\u1171\u11B6\u1110\u116D\u11B5\uD264cdbac";
+        pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.find());
+        assertEquals(mat.start(), 6);
+        assertEquals(mat.end(), 13);
+    }
+
+    public void testCanonEqFlagWithSupplementaryCharacters() {
+        // icu4c doesn't support CANON_EQ.
+        if (true) {
+            return;
+        }
+
+        /*
+        \u1D1BF->\u1D1BB\u1D16F->\u1D1B9\u1D165\u1D16F in UTF32
+        \uD834\uDDBF->\uD834\uDDBB\uD834\uDD6F
+        ->\uD834\uDDB9\uD834\uDD65\uD834\uDD6F in UTF16
+        */
+        String patString = "abc\uD834\uDDBFef";
+        String testString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef";
+        Pattern pat = Pattern.compile(patString, Pattern.CANON_EQ);
+        Matcher mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        testString = "abc\uD834\uDDBB\uD834\uDD6Fef";
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        patString = "abc\uD834\uDDBB\uD834\uDD6Fef";
+        testString = "abc\uD834\uDDBFef";
+        pat = Pattern.compile(patString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        testString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef";
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        patString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef";
+        testString = "abc\uD834\uDDBFef";
+        pat = Pattern.compile(patString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        testString = "abc\uD834\uDDBB\uD834\uDD6Fef";
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+
+        // Test supplementary characters with no decomposition
+        patString = "a\uD9A0\uDE8Ebc\uD834\uDDBB\uD834\uDD6Fe\uDE8Ef";
+        testString = "a\uD9A0\uDE8Ebc\uD834\uDDBFe\uDE8Ef";
+        pat = Pattern.compile(patString, Pattern.CANON_EQ);
+        mat = pat.matcher(testString);
+        assertTrue(mat.matches());
+    }
 }
diff --git a/luni/src/test/java/tests/api/java/lang/ProcessTest.java b/luni/src/test/java/tests/api/java/lang/ProcessTest.java
index f875dc0..2a8e0bd 100644
--- a/luni/src/test/java/tests/api/java/lang/ProcessTest.java
+++ b/luni/src/test/java/tests/api/java/lang/ProcessTest.java
@@ -17,192 +17,119 @@
 
 package tests.api.java.lang;
 
-import dalvik.annotation.BrokenTest;
-
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.ArrayList;
 
 public class ProcessTest extends junit.framework.TestCase {
 
-    /**
-     * java.lang.Process#getInputStream()
-     */
-    public void test_getInputStream() {
-        try {
-            // Test for:
-            //Object[] execArgs = Support_Exec.execJava2(
-            //        new String[] { "tests.support.Support_AvailTest" }, null,
-            //        true);
-            //Process proc = (Process) execArgs[0];
-
-            String[] commands = { "sleep", "1"};
-            Process proc = Runtime.getRuntime().exec(commands, null, null);
-
-            OutputStream os = proc.getOutputStream();
-
-            // first number indicates total stream length
-            // second number indicates length of data after second space
-            // this will allow us to verify length at start, middle, and end
-            os.write("10 5 abcde".getBytes());
-            os.close();
-
-            InputStream is = proc.getInputStream();
-            StringBuffer msg = new StringBuffer("");
-            while (true) {
-                int c = is.read();
-                if (c == -1)
-                    break;
-                msg.append((char) c);
-            }
-            is.close();
-            proc.waitFor();
-            //Support_Exec.checkStderr(execArgs);
-            proc.destroy();
-            assertEquals("true", msg.toString(), msg.toString());
-        } catch (IOException e) {
-            fail("IOException executing avail test: " + e);
-        } catch (InterruptedException e) {
-            fail("InterruptedException executing avail test: " + e);
-        }
+  public void test_55017() throws Exception {
+    ArrayList<Process> children = new ArrayList<Process>();
+    for (int i = 0; i < 256; ++i) {
+      try {
+        children.add(Runtime.getRuntime().exec(new String[] { "/system/bin/does-not-exist" }, null, null));
+        System.gc();
+      } catch (IOException expected) {
+      }
     }
+    assertEquals(0, children.size());
 
-    /**
-     * java.lang.Process#getOutputStream()
-     */
-    public void test_getOutputStream() {
-        try {
-            String[] commands = { "sleep", "1"};
-            Process proc = Runtime.getRuntime().exec(commands, null, null);
-            OutputStream os = proc.getOutputStream();
-            // send data, and check if it is echoed back correctly
-            String str1 = "Some data for testing communication between processes\n";
-            String str2 = "More data that serves the same purpose.\n";
-            String str3 = "Here is some more data.\n";
-            os.write(str1.getBytes());
-            try {
-                Thread.sleep(2000);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-            os.close();
-            InputStream is = proc.getInputStream();
-            StringBuffer msg = new StringBuffer("");
-            while (true) {
-                int c = is.read();
-                if (c == -1)
-                    break;
-                msg.append((char) c);
-            }
-            is.close();
-            proc.waitFor();
-            //Support_Exec.checkStderr(execArgs);
-            proc.destroy();
-            String org = str1;
-            String recvd = msg.toString();
-            // Doesn't pass on RI
-            // assertTrue("Data returned did not match data sent. Received: '"
-            //        + recvd + "' sent: '" + org + "'", recvd.equals(org));
-        } catch (IOException e) {
-            fail("IOException executing avail test: " + e);
-        } catch (InterruptedException e) {
-            fail("InterruptedException executing avail test: " + e);
-        }
+    boolean onDevice = new File("/system/bin").exists();
+    String[] psCommand = onDevice ? new String[] { "ps" } : new String[] { "ps", "s" };
+    Process ps = Runtime.getRuntime().exec(psCommand, null, null);
+    int zombieCount = 0;
+    for (String line : readAndCloseStream(ps.getInputStream()).split("\n")) {
+      if (line.contains(" Z ") || line.contains(" Z+ ")) {
+          ++zombieCount;
+      }
     }
+    assertEquals(0, zombieCount);
+  }
 
-    public void test_exitValue() {
-        try {
-            String[] commands = { "ls" };
-            Process process = Runtime.getRuntime().exec(commands, null, null);
-            try {
-                Thread.sleep(5000);
-            } catch(Exception e) {
-
-            }
-            assertTrue(process.exitValue() == 0);
-
-            String[] commandsSleep = { "sleep", "3" };
-            process = Runtime.getRuntime().exec(commandsSleep, null, null);
-            process.destroy();
-            try {
-                Thread.sleep(5000);
-            } catch (Exception e) {}
-            assertTrue(process.exitValue() != 0);
-
-            process = Runtime.getRuntime().exec(commandsSleep, null, null);
-            try {
-                process.exitValue();
-                fail("IllegalThreadStateException was not thrown.");
-            } catch(IllegalThreadStateException itse) {
-               //expected
-            }
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-        }
+  public void test_getOutputStream() throws Exception {
+    String[] commands = { "cat", "-"};
+    Process p = Runtime.getRuntime().exec(commands, null, null);
+    OutputStream os = p.getOutputStream();
+    // send data, and check if it is echoed back correctly
+    String str1 = "Some data for testing communication between processes\n";
+    String str2 = "More data that serves the same purpose.\n";
+    String str3 = "Here is some more data.\n";
+    os.write(str1.getBytes());
+    try {
+      Thread.sleep(1000);
+    } catch (InterruptedException e) {
+      e.printStackTrace();
     }
+    os.write(str2.getBytes());
+    os.write(str3.getBytes());
+    os.close();
 
-    public void test_Constructor() {
-        ProcessClass pc = new ProcessClass();
-        assertTrue(pc.exitValue() == 0);
+    String received = readAndCloseStream(p.getInputStream());
+    assertEquals(str1 + str2 + str3, received);
+
+    String stderr = readAndCloseStream(p.getErrorStream());
+    assertEquals("", stderr);
+
+    p.waitFor();
+    p.destroy();
+  }
+
+  public void test_getErrorStream() throws Exception {
+    String[] commands = { "cat", "--no-such-option"};
+    Process p = Runtime.getRuntime().exec(commands, null, null);
+
+    p.getOutputStream().close();
+
+    String received = readAndCloseStream(p.getInputStream());
+    assertEquals("", received);
+
+    String stderr = readAndCloseStream(p.getErrorStream());
+    assertTrue(stderr, stderr.contains("unrecognized option") || stderr.contains("invalid option"));
+
+    p.waitFor();
+    p.destroy();
+  }
+
+  private String readAndCloseStream(InputStream is) throws IOException {
+    StringBuffer result = new StringBuffer();
+    while (true) {
+      int c = is.read();
+      if (c == -1) {
+        break;
+      }
+      result.append((char) c);
     }
+    is.close();
+    return result.toString();
+  }
 
-    @BrokenTest("Sporadic timeouts in CTS, but not in CoreTestRunner")
-    public void test_destroy() {
-        String[] commands = { "ls"};
-        try {
-            Process process = Runtime.getRuntime().exec(commands, null, null);
-            process.destroy();
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-        }
+  public void test_exitValue() throws Exception {
+    String[] commands = { "ls" };
+    Process process = Runtime.getRuntime().exec(commands, null, null);
+    process.waitFor();
+    assertEquals(0, process.exitValue());
+
+    String[] commandsSleep = { "sleep", "3000" };
+    process = Runtime.getRuntime().exec(commandsSleep, null, null);
+    process.destroy();
+    process.waitFor(); // destroy is asynchronous.
+    assertTrue(process.exitValue() != 0);
+
+    process = Runtime.getRuntime().exec(new String[] { "sleep", "3000" }, null, null);
+    try {
+      process.exitValue();
+      fail();
+    } catch(IllegalThreadStateException expected) {
     }
+  }
 
-    protected void setUp() {
-    }
-
-    protected void tearDown() {
-    }
-
-    protected void doneSuite() {
-    }
-
-    class ProcessClass extends Process {
-
-        ProcessClass() {
-            super();
-        }
-
-        @Override
-        public void destroy() {
-
-        }
-
-        @Override
-        public int exitValue() {
-            // TODO Auto-generated method stub
-            return 0;
-        }
-
-        @Override
-        public InputStream getErrorStream() {
-            return null;
-        }
-
-        @Override
-        public InputStream getInputStream() {
-            return null;
-        }
-
-        @Override
-        public OutputStream getOutputStream() {
-            return null;
-        }
-
-        @Override
-        public int waitFor() throws InterruptedException {
-            // TODO Auto-generated method stub
-            return 0;
-        }
-
-    }
+  public void test_destroy() throws Exception {
+    String[] commands = { "ls"};
+    Process process = Runtime.getRuntime().exec(commands, null, null);
+    process.destroy();
+    process.destroy();
+    process.destroy();
+  }
 }
diff --git a/luni/src/test/java/tests/api/java/math/BigIntegerTest.java b/luni/src/test/java/tests/api/java/math/BigIntegerTest.java
deleted file mode 100644
index 2c2c25b..0000000
--- a/luni/src/test/java/tests/api/java/math/BigIntegerTest.java
+++ /dev/null
@@ -1,1185 +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 tests.api.java.math;
-
-import java.math.BigInteger;
-import java.util.Random;
-
-public class BigIntegerTest extends junit.framework.TestCase {
-
-    BigInteger minusTwo = new BigInteger("-2", 10);
-
-    BigInteger minusOne = new BigInteger("-1", 10);
-
-    BigInteger zero = new BigInteger("0", 10);
-
-    BigInteger one = new BigInteger("1", 10);
-
-    BigInteger two = new BigInteger("2", 10);
-
-    BigInteger ten = new BigInteger("10", 10);
-
-    BigInteger sixteen = new BigInteger("16", 10);
-
-    BigInteger oneThousand = new BigInteger("1000", 10);
-
-    BigInteger aZillion = new BigInteger(
-            "100000000000000000000000000000000000000000000000000", 10);
-
-    BigInteger twoToTheTen = new BigInteger("1024", 10);
-
-    BigInteger twoToTheSeventy = two.pow(70);
-
-    Random rand = new Random();
-
-    BigInteger bi;
-
-    BigInteger bi1;
-
-    BigInteger bi2;
-
-    BigInteger bi3;
-
-    BigInteger bi11;
-
-    BigInteger bi22;
-
-    BigInteger bi33;
-
-    BigInteger bi12;
-
-    BigInteger bi23;
-
-    BigInteger bi13;
-
-    BigInteger largePos;
-
-    BigInteger smallPos;
-
-    BigInteger largeNeg;
-
-    BigInteger smallNeg;
-
-    BigInteger[][] booleanPairs;
-
-    /**
-     * java.math.BigInteger#BigInteger(int, java.util.Random)
-     */
-    public void test_ConstructorILjava_util_Random() {
-        // regression test for HARMONY-1047
-        try {
-            new BigInteger(Integer.MAX_VALUE, (Random)null);
-            fail("NegativeArraySizeException expected");
-        } catch (NegativeArraySizeException e) {
-            // PASSED
-        }
-
-        bi = new BigInteger(70, rand);
-        bi2 = new BigInteger(70, rand);
-        assertTrue("Random number is negative", bi.compareTo(zero) >= 0);
-        assertTrue("Random number is too big",
-                bi.compareTo(twoToTheSeventy) < 0);
-        assertTrue(
-                "Two random numbers in a row are the same (might not be a bug but it very likely is)",
-                !bi.equals(bi2));
-        assertTrue("Not zero", new BigInteger(0, rand).equals(BigInteger.ZERO));
-
-        try {
-            new BigInteger(-1, (Random)null);
-            fail("IllegalArgumentException expected");
-        } catch (IllegalArgumentException e) {
-            // PASSED
-        }
-    }
-
-    /**
-     * java.math.BigInteger#BigInteger(int, int, java.util.Random)
-     */
-    // BIGNUM returns no Primes smaller than 16 bits.
-    public void test_ConstructorIILjava_util_Random() {
-        bi = new BigInteger(10, 5, rand);
-        bi2 = new BigInteger(10, 5, rand);
-        assertTrue("Random number one is negative", bi.compareTo(zero) >= 0);
-        assertTrue("Random number one is too big",
-                bi.compareTo(twoToTheTen) < 0);
-        assertTrue("Random number two is negative", bi2.compareTo(zero) >= 0);
-        assertTrue("Random number two is too big",
-                bi2.compareTo(twoToTheTen) < 0);
-
-        Random rand = new Random();
-        BigInteger bi;
-        int certainty[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
-                Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -2, -1 };
-        for (int i = 2; i <= 20; i++) {
-            for (int c = 0; c < certainty.length; c++) {
-                bi = new BigInteger(i, c, rand); // Create BigInteger
-                assertTrue("Bit length incorrect", bi.bitLength() == i);
-            }
-        }
-
-        try {
-            new BigInteger(1, 80, (Random)null);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-            // PASSED
-        }
-
-        try {
-            new BigInteger(-1, (Random)null);
-            fail("IllegalArgumentException expected");
-        } catch (IllegalArgumentException e) {
-            // PASSED
-        }
-    }
-
-    /**
-     * java.math.BigInteger#BigInteger(byte[])
-     */
-    public void test_Constructor$B() {
-        byte[] myByteArray;
-        myByteArray = new byte[] { (byte) 0x00, (byte) 0xFF, (byte) 0xFE };
-        bi = new BigInteger(myByteArray);
-        assertTrue("Incorrect value for pos number", bi.equals(BigInteger.ZERO
-                .setBit(16).subtract(two)));
-        myByteArray = new byte[] { (byte) 0xFF, (byte) 0xFE };
-        bi = new BigInteger(myByteArray);
-        assertTrue("Incorrect value for neg number", bi.equals(minusTwo));
-    }
-
-    /**
-     * java.math.BigInteger#BigInteger(int, byte[])
-     */
-    public void test_ConstructorI$B() {
-        byte[] myByteArray;
-        myByteArray = new byte[] { (byte) 0xFF, (byte) 0xFE };
-        bi = new BigInteger(1, myByteArray);
-        assertTrue("Incorrect value for pos number", bi.equals(BigInteger.ZERO
-                .setBit(16).subtract(two)));
-        bi = new BigInteger(-1, myByteArray);
-        assertTrue("Incorrect value for neg number", bi.equals(BigInteger.ZERO
-                .setBit(16).subtract(two).negate()));
-        myByteArray = new byte[] { (byte) 0, (byte) 0 };
-        bi = new BigInteger(0, myByteArray);
-        assertTrue("Incorrect value for zero", bi.equals(zero));
-        myByteArray = new byte[] { (byte) 1 };
-        try {
-            new BigInteger(0, myByteArray);
-            fail("Failed to throw NumberFormatException");
-        } catch (NumberFormatException e) {
-            // correct
-        }
-    }
-
-    /**
-     * java.math.BigInteger#BigInteger(java.lang.String)
-     */
-    public void test_constructor_String_empty() {
-        try {
-            new BigInteger("");
-            fail("Expected NumberFormatException for new BigInteger(\"\")");
-        } catch (NumberFormatException e) {
-        }
-    }
-
-    /**
-     * java.math.BigInteger#toByteArray()
-     */
-    public void test_toByteArray() {
-        byte[] myByteArray, anotherByteArray;
-        myByteArray = new byte[] { 97, 33, 120, 124, 50, 2, 0, 0, 0, 12, 124,
-                42 };
-        anotherByteArray = new BigInteger(myByteArray).toByteArray();
-        assertTrue("Incorrect byte array returned",
-                myByteArray.length == anotherByteArray.length);
-        for (int counter = myByteArray.length - 1; counter >= 0; counter--) {
-            assertTrue("Incorrect values in returned byte array",
-                    myByteArray[counter] == anotherByteArray[counter]);
-        }
-    }
-
-//    public void test_SpecialPrimes() {
-//        System.out.println("test_SpecialPrimes");
-//        final BigInteger TWO = BigInteger.valueOf(2);
-//        BigInteger p, q;
-//        for (;;) {
-//            p = new BigInteger(1024, 23, new Random());
-//            q = p.subtract(BigInteger.ONE).divide(TWO);
-//            if (q.isProbablePrime(20)) {
-//                System.out.println(q);
-//                System.out.println(p);
-//                break;
-//            }
-//            System.out.print(".");
-//        }
-//        fail("isProbablePrime failed for: " + bi);
-//    }
-
-    /**
-     * java.math.BigInteger#isProbablePrime(int)
-     */
-    public void test_isProbablePrimeI() {
-        int fails = 0;
-        bi = new BigInteger(20, 20, rand);
-        if (!bi.isProbablePrime(17)) {
-            fails++;
-        }
-        bi = new BigInteger("4", 10);
-        if (bi.isProbablePrime(17)) {
-            fail("isProbablePrime failed for: " + bi);
-        }
-        bi = BigInteger.valueOf(17L * 13L);
-        if (bi.isProbablePrime(17)) {
-            fail("isProbablePrime failed for: " + bi);
-        }
-        for (long a = 2; a < 1000; a++) {
-            if (isPrime(a)) {
-                assertTrue("false negative on prime number <1000", BigInteger
-                        .valueOf(a).isProbablePrime(5));
-            } else if (BigInteger.valueOf(a).isProbablePrime(17)) {
-                System.out.println("isProbablePrime failed for: " + a);
-                fails++;
-            }
-        }
-        for (int a = 0; a < 1000; a++) {
-            bi = BigInteger.valueOf(rand.nextInt(1000000)).multiply(
-                    BigInteger.valueOf(rand.nextInt(1000000)));
-            if (bi.isProbablePrime(17)) {
-                System.out.println("isProbablePrime failed for: " + bi);
-                fails++;
-            }
-        }
-        for (int a = 0; a < 200; a++) {
-            bi = new BigInteger(70, rand).multiply(new BigInteger(70, rand));
-            if (bi.isProbablePrime(17)) {
-                System.out.println("isProbablePrime failed for: " + bi);
-                fails++;
-            }
-        }
-        assertTrue("Too many false positives - may indicate a problem",
-                fails <= 1);
-
-        //
-        // And now some tests on real big integers:
-        //
-        bi = new BigInteger("153890972191202256150310830154922163807316525358455215516067727076235016932726922093888770552128767458882963869421440585369743", 10);
-        if (!bi.isProbablePrime(80)) {
-            fail("isProbablePrime failed for: " + bi);
-        }
-        bi = new BigInteger("2090575416269141767246491983797422123741252476560371649798066134123893524014911825188890458270426076468664046568752890122415061377308817346303546688282957897504000216241497550243010257911214329646877810655164658470278901030511157372440751259674247310396158238588463284702737181653", 10);
-        if (!bi.isProbablePrime(80)) {
-            fail("isProbablePrime failed for: " + bi);
-        }
-        //
-        for (int bitLength = 100; bitLength <= 600; bitLength += 100) {
-            BigInteger a = BigInteger.probablePrime(bitLength, rand);
-            BigInteger b = BigInteger.probablePrime(bitLength, rand);
-            BigInteger c = a.multiply(b);
-            assertFalse("isProbablePrime failed for product of two large primes" +
-                            a + " * " + b + " = " + c +
-                            " (bitLength = " + bitLength + ")",
-                    c.isProbablePrime(80) );
-        }
-    }
-
-    /**
-     * java.math.BigInteger#nextProbablePrime()
-     */
-    public void test_nextProbablePrime() {
-        largePrimesProduct(
-                new BigInteger("2537895984043447429238717358455377929009126353874925049325287329295635198252046158619999217453233889378619619008359011789"),
-                new BigInteger("1711501451602688337873833423534849678524059393231999670806585630179374689152366029939952735718718709436427337762082614710093"),
-                "4343612660706993434504106787562106084038357258130862545477481433639575850237346784798851102536616749334772541987502120552264920040629526028540204698334741815536099373917351194423681128374184971846099257056996626343051832131340568120612204287123"
-        );
-
-        largePrimesProduct(
-                new BigInteger("4617974730611208463200675282934641082129817404749925308887287017217158545765190433369842932770197341032031682222405074564586462802072184047198214312142847809259437477387527466762251087500170588962277514858557309036550499896961735701485020851"),
-                new BigInteger("4313158964405728158057980867015758419530142215799386331265837224051830838583266274443105715022196238165196727467066901495701708590167750818040112544031694506528759169669442493029999154074962566165293254671176670719518898684698255068313216294333"),
-                "19918059106734861363335842730108905466210762564765297409619920041621379008685530738918145604092111306972524565803236031571858280032420140331838737621152630780261815015157696362550138161774466814661069892975003440654998880587960037013294137372709096788892473385003457361736563927256562678181177287998121131179907762285048659075843995525830945659905573174849006768920618442371027575308854641789533211132313916836205357976988977849024687805212304038260207820679964201211309384057458137851"
-        );
-    }
-
-    static void largePrimesProduct(BigInteger a, BigInteger b, String c) {
-        BigInteger wp = a.multiply(b);
-        assertFalse("isProbablePrime failed for product of two large primes" +
-                        a + " * " + b + " = " + c,
-                wp.isProbablePrime(80) );
-        BigInteger wpMinusOne = wp.subtract(BigInteger.ONE);
-        BigInteger next = wpMinusOne.nextProbablePrime();
-//        System.out.println(c);
-//        System.out.println(next);
-        assertTrue("nextProbablePrime returns wrong number: " + next +
-                        "instead of expected: " + c,
-                next.toString().equals(c) );
-    }
-
-    /**
-     * java.math.BigInteger#probablePrime(int, java.util.Random)
-     */
-    public void test_probablePrime() {
-        for (int bitLength = 50; bitLength <= 1050; bitLength += 100) {
-            BigInteger a = BigInteger.probablePrime(bitLength, rand);
-            assertTrue("isProbablePrime(probablePrime()) failed for: " + bi,
-                    a.isProbablePrime(80));
-//            System.out.println(a);
-//            BigInteger prime = a.nextProbablePrime();
-//            System.out.print("Next Probable Prime is ");
-//            System.out.println(prime);
-        }
-    }
-
-// BEGIN android-added
-//    public void testModPowPerformance() {
-//        Random rnd = new Random();
-//        for (int i = 0; i < 10; i++) {
-//            BigInteger a = new BigInteger(512, rnd);
-//            BigInteger m = new BigInteger(1024, rnd);
-//            BigInteger p = new BigInteger(256, rnd);
-//            BigInteger mp = a.modPow(p, m);
-//            System.out.println(mp);
-//        }
-//    }
-
-// shows factor 20 speed up (BIGNUM to Harmony Java):
-//    public void testNextProbablePrime() {
-//        Random rnd = new Random();
-//        rnd.setSeed(0);
-//        for (int i = 1; i <= 32; i += 1) {
-//            BigInteger a = new BigInteger(i, rnd);
-//            System.out.println(a);
-//            BigInteger prime = a.nextProbablePrime();
-//            System.out.print("Next Probable Prime is ");
-//            System.out.println(prime);
-//        }
-//        for (int i = 1; i <= 32; i += 4) {
-//            BigInteger a = new BigInteger(32 * i, rnd);
-//            System.out.println(a);
-//            BigInteger prime = a.nextProbablePrime();
-//            System.out.print("Next Probable Prime is ");
-//            System.out.println(prime);
-//        }
-//    }
-
-// shows factor 20 speed up (BIGNUM to Harmony Java):
-// shows that certainty 80 is "practically aquivalent" to certainty 100
-//    public void testPrimeGenPerformance() {
-//        Random rnd = new Random();
-//        rnd.setSeed(0);
-//        for (int i = 1; i <= 32; i +=8 ) {
-//            BigInteger a = new BigInteger(32 * i, 80, rnd);
-//            System.out.println(a);
-//            System.out.println("Now testing it again:");
-//            if (a.isProbablePrime(100)) {
-//                System.out.println("************************ PASSED! **************************");
-//            } else {
-//                System.out.println("************************ FAILED!!! **************************");
-//                System.out.println("************************ FAILED!!! **************************");
-//                System.out.println("************************ FAILED!!! **************************");
-//                System.out.println("************************ FAILED!!! **************************");
-//                System.out.println("************************ FAILED!!! **************************");
-//                System.out.println("************************ FAILED!!! **************************");
-//            }
-//        }
-//    }
-// END android-added
-
-
-
-    /**
-     * java.math.BigInteger#equals(java.lang.Object)
-     */
-    public void test_equalsLjava_lang_Object() {
-        assertTrue("0=0", zero.equals(BigInteger.valueOf(0)));
-        assertTrue("-123=-123", BigInteger.valueOf(-123).equals(
-                BigInteger.valueOf(-123)));
-        assertTrue("0=1", !zero.equals(one));
-        assertTrue("0=-1", !zero.equals(minusOne));
-        assertTrue("1=-1", !one.equals(minusOne));
-        assertTrue("bi3=bi3", bi3.equals(bi3));
-        assertTrue("bi3=copy of bi3", bi3.equals(bi3.negate().negate()));
-        assertTrue("bi3=bi2", !bi3.equals(bi2));
-    }
-
-    /**
-     * java.math.BigInteger#compareTo(java.math.BigInteger)
-     */
-    public void test_compareToLjava_math_BigInteger() {
-        assertTrue("Smaller number returned >= 0", one.compareTo(two) < 0);
-        assertTrue("Larger number returned >= 0", two.compareTo(one) > 0);
-        assertTrue("Equal numbers did not return 0", one.compareTo(one) == 0);
-        assertTrue("Neg number messed things up",
-                two.negate().compareTo(one) < 0);
-    }
-
-    /**
-     * java.math.BigInteger#intValue()
-     */
-    public void test_intValue() {
-        assertTrue("Incorrect intValue for 2**70",
-                twoToTheSeventy.intValue() == 0);
-        assertTrue("Incorrect intValue for 2", two.intValue() == 2);
-    }
-
-    /**
-     * java.math.BigInteger#longValue()
-     */
-    public void test_longValue() {
-        assertTrue("Incorrect longValue for 2**70",
-                twoToTheSeventy.longValue() == 0);
-        assertTrue("Incorrect longValue for 2", two.longValue() == 2);
-    }
-
-    /**
-     * java.math.BigInteger#valueOf(long)
-     */
-    public void test_valueOfJ() {
-        assertTrue("Incurred number returned for 2", BigInteger.valueOf(2L)
-                .equals(two));
-        assertTrue("Incurred number returned for 200", BigInteger.valueOf(200L)
-                .equals(BigInteger.valueOf(139).add(BigInteger.valueOf(61))));
-    }
-
-    /**
-     * java.math.BigInteger#add(java.math.BigInteger)
-     */
-    public void test_addLjava_math_BigInteger() {
-        assertTrue("Incorrect sum--wanted a zillion", aZillion.add(aZillion)
-                .add(aZillion.negate()).equals(aZillion));
-        assertTrue("0+0", zero.add(zero).equals(zero));
-        assertTrue("0+1", zero.add(one).equals(one));
-        assertTrue("1+0", one.add(zero).equals(one));
-        assertTrue("1+1", one.add(one).equals(two));
-        assertTrue("0+(-1)", zero.add(minusOne).equals(minusOne));
-        assertTrue("(-1)+0", minusOne.add(zero).equals(minusOne));
-        assertTrue("(-1)+(-1)", minusOne.add(minusOne).equals(minusTwo));
-        assertTrue("1+(-1)", one.add(minusOne).equals(zero));
-        assertTrue("(-1)+1", minusOne.add(one).equals(zero));
-
-        for (int i = 0; i < 200; i++) {
-            BigInteger midbit = zero.setBit(i);
-            assertTrue("add fails to carry on bit " + i, midbit.add(midbit)
-                    .equals(zero.setBit(i + 1)));
-        }
-        BigInteger bi2p3 = bi2.add(bi3);
-        BigInteger bi3p2 = bi3.add(bi2);
-        assertTrue("bi2p3=bi3p2", bi2p3.equals(bi3p2));
-
-
-        // BESSER UEBERGREIFENDE TESTS MACHEN IN FORM VON STRESS TEST.
-        // add large positive + small positive
-        BigInteger sum = aZillion;
-        BigInteger increment = one;
-        for (int i = 0; i < 20; i++) {
-
-        }
-
-        // add large positive + small negative
-
-        // add large negative + small positive
-
-        // add large negative + small negative
-    }
-
-    /**
-     * java.math.BigInteger#negate()
-     */
-    public void test_negate() {
-        assertTrue("Single negation of zero did not result in zero", zero
-                .negate().equals(zero));
-        assertTrue("Single negation resulted in original nonzero number",
-                !aZillion.negate().equals(aZillion));
-        assertTrue("Double negation did not result in original number",
-                aZillion.negate().negate().equals(aZillion));
-
-        assertTrue("0.neg", zero.negate().equals(zero));
-        assertTrue("1.neg", one.negate().equals(minusOne));
-        assertTrue("2.neg", two.negate().equals(minusTwo));
-        assertTrue("-1.neg", minusOne.negate().equals(one));
-        assertTrue("-2.neg", minusTwo.negate().equals(two));
-        assertTrue("0x62EB40FEF85AA9EBL*2.neg", BigInteger.valueOf(
-                0x62EB40FEF85AA9EBL * 2).negate().equals(
-                BigInteger.valueOf(-0x62EB40FEF85AA9EBL * 2)));
-        for (int i = 0; i < 200; i++) {
-            BigInteger midbit = zero.setBit(i);
-            BigInteger negate = midbit.negate();
-            assertTrue("negate negate", negate.negate().equals(midbit));
-            assertTrue("neg fails on bit " + i, midbit.negate().add(midbit)
-                    .equals(zero));
-        }
-    }
-
-    /**
-     * java.math.BigInteger#signum()
-     */
-    public void test_signum() {
-        assertTrue("Wrong positive signum", two.signum() == 1);
-        assertTrue("Wrong zero signum", zero.signum() == 0);
-        assertTrue("Wrong neg zero signum", zero.negate().signum() == 0);
-        assertTrue("Wrong neg signum", two.negate().signum() == -1);
-    }
-
-    /**
-     * java.math.BigInteger#abs()
-     */
-    public void test_abs() {
-        assertTrue("Invalid number returned for zillion", aZillion.negate()
-                .abs().equals(aZillion.abs()));
-        assertTrue("Invalid number returned for zero neg", zero.negate().abs()
-                .equals(zero));
-        assertTrue("Invalid number returned for zero", zero.abs().equals(zero));
-        assertTrue("Invalid number returned for two", two.negate().abs()
-                .equals(two));
-    }
-
-    /**
-     * java.math.BigInteger#pow(int)
-     */
-    public void test_powI() {
-        assertTrue("Incorrect exponent returned for 2**10", two.pow(10).equals(
-                twoToTheTen));
-        assertTrue("Incorrect exponent returned for 2**70", two.pow(30)
-                .multiply(two.pow(40)).equals(twoToTheSeventy));
-        assertTrue("Incorrect exponent returned for 10**50", ten.pow(50)
-                .equals(aZillion));
-    }
-
-    /**
-     * java.math.BigInteger#modInverse(java.math.BigInteger)
-     */
-    public void test_modInverseLjava_math_BigInteger() {
-        BigInteger a = zero, mod, inv;
-        for (int j = 3; j < 50; j++) {
-            mod = BigInteger.valueOf(j);
-            for (int i = -j + 1; i < j; i++) {
-                try {
-                    a = BigInteger.valueOf(i);
-                    inv = a.modInverse(mod);
-                    assertTrue("bad inverse: " + a + " inv mod " + mod
-                            + " equals " + inv, one.equals(a.multiply(inv).mod(
-                            mod)));
-                    assertTrue("inverse greater than modulo: " + a
-                            + " inv mod " + mod + " equals " + inv, inv
-                            .compareTo(mod) < 0);
-                    assertTrue("inverse less than zero: " + a + " inv mod "
-                            + mod + " equals " + inv, inv
-                            .compareTo(BigInteger.ZERO) >= 0);
-                } catch (ArithmeticException e) {
-                    assertTrue("should have found inverse for " + a + " mod "
-                            + mod, !one.equals(a.gcd(mod)));
-                }
-            }
-        }
-        for (int j = 1; j < 10; j++) {
-            mod = bi2.add(BigInteger.valueOf(j));
-            for (int i = 0; i < 20; i++) {
-                try {
-                    a = bi3.add(BigInteger.valueOf(i));
-                    inv = a.modInverse(mod);
-                    assertTrue("bad inverse: " + a + " inv mod " + mod
-                            + " equals " + inv, one.equals(a.multiply(inv).mod(
-                            mod)));
-                    assertTrue("inverse greater than modulo: " + a
-                            + " inv mod " + mod + " equals " + inv, inv
-                            .compareTo(mod) < 0);
-                    assertTrue("inverse less than zero: " + a + " inv mod "
-                            + mod + " equals " + inv, inv
-                            .compareTo(BigInteger.ZERO) >= 0);
-                } catch (ArithmeticException e) {
-                    assertTrue("should have found inverse for " + a + " mod "
-                            + mod, !one.equals(a.gcd(mod)));
-                }
-            }
-        }
-    }
-
-    /**
-     * java.math.BigInteger#shiftRight(int)
-     */
-    public void test_shiftRightI() {
-        assertTrue("1 >> 0", BigInteger.valueOf(1).shiftRight(0).equals(
-                BigInteger.ONE));
-        assertTrue("1 >> 1", BigInteger.valueOf(1).shiftRight(1).equals(
-                BigInteger.ZERO));
-        assertTrue("1 >> 63", BigInteger.valueOf(1).shiftRight(63).equals(
-                BigInteger.ZERO));
-        assertTrue("1 >> 64", BigInteger.valueOf(1).shiftRight(64).equals(
-                BigInteger.ZERO));
-        assertTrue("1 >> 65", BigInteger.valueOf(1).shiftRight(65).equals(
-                BigInteger.ZERO));
-        assertTrue("1 >> 1000", BigInteger.valueOf(1).shiftRight(1000).equals(
-                BigInteger.ZERO));
-        assertTrue("-1 >> 0", BigInteger.valueOf(-1).shiftRight(0).equals(
-                minusOne));
-        assertTrue("-1 >> 1", BigInteger.valueOf(-1).shiftRight(1).equals(
-                minusOne));
-        assertTrue("-1 >> 63", BigInteger.valueOf(-1).shiftRight(63).equals(
-                minusOne));
-        assertTrue("-1 >> 64", BigInteger.valueOf(-1).shiftRight(64).equals(
-                minusOne));
-        assertTrue("-1 >> 65", BigInteger.valueOf(-1).shiftRight(65).equals(
-                minusOne));
-        assertTrue("-1 >> 1000", BigInteger.valueOf(-1).shiftRight(1000)
-                .equals(minusOne));
-
-        BigInteger a = BigInteger.ONE;
-        BigInteger c = bi3;
-        BigInteger E = bi3.negate();
-        BigInteger e = E;
-        for (int i = 0; i < 200; i++) {
-            BigInteger b = BigInteger.ZERO.setBit(i);
-            assertTrue("a==b", a.equals(b));
-            a = a.shiftLeft(1);
-            assertTrue("a non-neg", a.signum() >= 0);
-
-            BigInteger d = bi3.shiftRight(i);
-            assertTrue("c==d", c.equals(d));
-            c = c.shiftRight(1);
-            assertTrue(">>1 == /2", d.divide(two).equals(c));
-            assertTrue("c non-neg", c.signum() >= 0);
-
-            BigInteger f = E.shiftRight(i);
-            assertTrue("e==f", e.equals(f));
-            e = e.shiftRight(1);
-            assertTrue(">>1 == /2", f.subtract(one).divide(two).equals(e));
-            assertTrue("e negative", e.signum() == -1);
-
-            assertTrue("b >> i", b.shiftRight(i).equals(one));
-            assertTrue("b >> i+1", b.shiftRight(i + 1).equals(zero));
-            assertTrue("b >> i-1", b.shiftRight(i - 1).equals(two));
-        }
-    }
-
-    /**
-     * java.math.BigInteger#shiftLeft(int)
-     */
-    public void test_shiftLeftI() {
-        assertTrue("1 << 0", one.shiftLeft(0).equals(one));
-        assertTrue("1 << 1", one.shiftLeft(1).equals(two));
-        assertTrue("1 << 63", one.shiftLeft(63).equals(
-                new BigInteger("8000000000000000", 16)));
-        assertTrue("1 << 64", one.shiftLeft(64).equals(
-                new BigInteger("10000000000000000", 16)));
-        assertTrue("1 << 65", one.shiftLeft(65).equals(
-                new BigInteger("20000000000000000", 16)));
-        assertTrue("-1 << 0", minusOne.shiftLeft(0).equals(minusOne));
-        assertTrue("-1 << 1", minusOne.shiftLeft(1).equals(minusTwo));
-        assertTrue("-1 << 63", minusOne.shiftLeft(63).equals(
-                new BigInteger("-9223372036854775808")));
-        assertTrue("-1 << 64", minusOne.shiftLeft(64).equals(
-                new BigInteger("-18446744073709551616")));
-        assertTrue("-1 << 65", minusOne.shiftLeft(65).equals(
-                new BigInteger("-36893488147419103232")));
-
-        BigInteger a = bi3;
-        BigInteger c = minusOne;
-        for (int i = 0; i < 200; i++) {
-            BigInteger b = bi3.shiftLeft(i);
-            assertTrue("a==b", a.equals(b));
-            assertTrue("a >> i == bi3", a.shiftRight(i).equals(bi3));
-            a = a.shiftLeft(1);
-            assertTrue("<<1 == *2", b.multiply(two).equals(a));
-            assertTrue("a non-neg", a.signum() >= 0);
-            assertTrue("a.bitCount==b.bitCount", a.bitCount() == b.bitCount());
-
-            BigInteger d = minusOne.shiftLeft(i);
-            assertTrue("c==d", c.equals(d));
-            c = c.shiftLeft(1);
-            assertTrue("<<1 == *2 negative", d.multiply(two).equals(c));
-            assertTrue("c negative", c.signum() == -1);
-            assertTrue("d >> i == minusOne", d.shiftRight(i).equals(minusOne));
-        }
-    }
-
-    /**
-     * java.math.BigInteger#multiply(java.math.BigInteger)
-     */
-    public void test_multiplyLjava_math_BigInteger() {
-        assertTrue("Incorrect sum--wanted three zillion", aZillion
-                .add(aZillion).add(aZillion).equals(
-                        aZillion.multiply(new BigInteger("3", 10))));
-
-        assertTrue("0*0", zero.multiply(zero).equals(zero));
-        assertTrue("0*1", zero.multiply(one).equals(zero));
-        assertTrue("1*0", one.multiply(zero).equals(zero));
-        assertTrue("1*1", one.multiply(one).equals(one));
-        assertTrue("0*(-1)", zero.multiply(minusOne).equals(zero));
-        assertTrue("(-1)*0", minusOne.multiply(zero).equals(zero));
-        assertTrue("(-1)*(-1)", minusOne.multiply(minusOne).equals(one));
-        assertTrue("1*(-1)", one.multiply(minusOne).equals(minusOne));
-        assertTrue("(-1)*1", minusOne.multiply(one).equals(minusOne));
-
-        testAllMults(bi1, bi1, bi11);
-        testAllMults(bi2, bi2, bi22);
-        testAllMults(bi3, bi3, bi33);
-        testAllMults(bi1, bi2, bi12);
-        testAllMults(bi1, bi3, bi13);
-        testAllMults(bi2, bi3, bi23);
-    }
-
-    /**
-     * java.math.BigInteger#divide(java.math.BigInteger)
-     */
-    public void test_divideLjava_math_BigInteger() {
-        testAllDivs(bi33, bi3);
-        testAllDivs(bi22, bi2);
-        testAllDivs(bi11, bi1);
-        testAllDivs(bi13, bi1);
-        testAllDivs(bi13, bi3);
-        testAllDivs(bi12, bi1);
-        testAllDivs(bi12, bi2);
-        testAllDivs(bi23, bi2);
-        testAllDivs(bi23, bi3);
-        testAllDivs(largePos, bi1);
-        testAllDivs(largePos, bi2);
-        testAllDivs(largePos, bi3);
-        testAllDivs(largeNeg, bi1);
-        testAllDivs(largeNeg, bi2);
-        testAllDivs(largeNeg, bi3);
-        testAllDivs(largeNeg, largePos);
-        testAllDivs(largePos, largeNeg);
-        testAllDivs(bi3, bi3);
-        testAllDivs(bi2, bi2);
-        testAllDivs(bi1, bi1);
-        testDivRanges(bi1);
-        testDivRanges(bi2);
-        testDivRanges(bi3);
-        testDivRanges(smallPos);
-        testDivRanges(largePos);
-        testDivRanges(new BigInteger("62EB40FEF85AA9EB", 16));
-        testAllDivs(BigInteger.valueOf(0xCC0225953CL), BigInteger
-                .valueOf(0x1B937B765L));
-
-        try {
-            largePos.divide(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            bi1.divide(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            bi3.negate().divide(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            zero.divide(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-    }
-
-    /**
-     * java.math.BigInteger#remainder(java.math.BigInteger)
-     */
-    public void test_remainderLjava_math_BigInteger() {
-        try {
-            largePos.remainder(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            bi1.remainder(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            bi3.negate().remainder(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            zero.remainder(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-    }
-
-    /**
-     * java.math.BigInteger#mod(java.math.BigInteger)
-     */
-    public void test_modLjava_math_BigInteger() {
-        try {
-            largePos.mod(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            bi1.mod(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            bi3.negate().mod(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            zero.mod(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-    }
-
-    /**
-     * java.math.BigInteger#divideAndRemainder(java.math.BigInteger)
-     */
-    public void test_divideAndRemainderLjava_math_BigInteger() {
-        try {
-            largePos.divideAndRemainder(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            bi1.divideAndRemainder(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            bi3.negate().divideAndRemainder(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-
-        try {
-            zero.divideAndRemainder(zero);
-            fail("ArithmeticException expected");
-        } catch (ArithmeticException e) {
-        }
-    }
-
-    /**
-     * java.math.BigInteger#BigInteger(java.lang.String)
-     */
-    public void test_ConstructorLjava_lang_String() {
-        assertTrue("new(0)", new BigInteger("0").equals(BigInteger.valueOf(0)));
-        assertTrue("new(1)", new BigInteger("1").equals(BigInteger.valueOf(1)));
-        assertTrue("new(12345678901234)", new BigInteger("12345678901234")
-                .equals(BigInteger.valueOf(12345678901234L)));
-        assertTrue("new(-1)", new BigInteger("-1").equals(BigInteger
-                .valueOf(-1)));
-        assertTrue("new(-12345678901234)", new BigInteger("-12345678901234")
-                .equals(BigInteger.valueOf(-12345678901234L)));
-    }
-
-    /**
-     * java.math.BigInteger#BigInteger(java.lang.String, int)
-     */
-    public void test_ConstructorLjava_lang_StringI() {
-        assertTrue("new(0,16)", new BigInteger("0", 16).equals(BigInteger
-                .valueOf(0)));
-        assertTrue("new(1,16)", new BigInteger("1", 16).equals(BigInteger
-                .valueOf(1)));
-        assertTrue("new(ABF345678901234,16)", new BigInteger("ABF345678901234",
-                16).equals(BigInteger.valueOf(0xABF345678901234L)));
-        assertTrue("new(abf345678901234,16)", new BigInteger("abf345678901234",
-                16).equals(BigInteger.valueOf(0xABF345678901234L)));
-        assertTrue("new(-1,16)", new BigInteger("-1", 16).equals(BigInteger
-                .valueOf(-1)));
-        assertTrue("new(-ABF345678901234,16)", new BigInteger(
-                "-ABF345678901234", 16).equals(BigInteger
-                .valueOf(-0xABF345678901234L)));
-        assertTrue("new(-abf345678901234,16)", new BigInteger(
-                "-abf345678901234", 16).equals(BigInteger
-                .valueOf(-0xABF345678901234L)));
-        assertTrue("new(-101010101,2)", new BigInteger("-101010101", 2)
-                .equals(BigInteger.valueOf(-341)));
-    }
-
-    /**
-     * java.math.BigInteger#toString()
-     */
-    public void test_toString() {
-        assertTrue("0.toString", "0".equals(BigInteger.valueOf(0).toString()));
-        assertTrue("1.toString", "1".equals(BigInteger.valueOf(1).toString()));
-        assertTrue("12345678901234.toString", "12345678901234"
-                .equals(BigInteger.valueOf(12345678901234L).toString()));
-        assertTrue("-1.toString", "-1"
-                .equals(BigInteger.valueOf(-1).toString()));
-        assertTrue("-12345678901234.toString", "-12345678901234"
-                .equals(BigInteger.valueOf(-12345678901234L).toString()));
-    }
-
-    /**
-     * java.math.BigInteger#toString(int)
-     */
-    public void test_toStringI() {
-        assertTrue("0.toString(16)", "0".equals(BigInteger.valueOf(0).toString(
-                16)));
-        assertTrue("1.toString(16)", "1".equals(BigInteger.valueOf(1).toString(
-                16)));
-        assertTrue("ABF345678901234.toString(16)", "abf345678901234"
-                .equals(BigInteger.valueOf(0xABF345678901234L).toString(16)));
-        assertTrue("-1.toString(16)", "-1".equals(BigInteger.valueOf(-1)
-                .toString(16)));
-        assertTrue("-ABF345678901234.toString(16)", "-abf345678901234"
-                .equals(BigInteger.valueOf(-0xABF345678901234L).toString(16)));
-        assertTrue("-101010101.toString(2)", "-101010101".equals(BigInteger
-                .valueOf(-341).toString(2)));
-    }
-
-    /**
-     * java.math.BigInteger#and(java.math.BigInteger)
-     */
-    public void test_andLjava_math_BigInteger() {
-        for (BigInteger[] element : booleanPairs) {
-            BigInteger i1 = element[0], i2 = element[1];
-            BigInteger res = i1.and(i2);
-            assertTrue("symmetry of and", res.equals(i2.and(i1)));
-            int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
-            for (int i = 0; i < len; i++) {
-                assertTrue("and", (i1.testBit(i) && i2.testBit(i)) == res
-                        .testBit(i));
-            }
-        }
-    }
-
-    /**
-     * java.math.BigInteger#or(java.math.BigInteger)
-     */
-    public void test_orLjava_math_BigInteger() {
-        for (BigInteger[] element : booleanPairs) {
-            BigInteger i1 = element[0], i2 = element[1];
-            BigInteger res = i1.or(i2);
-            assertTrue("symmetry of or", res.equals(i2.or(i1)));
-            int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
-            for (int i = 0; i < len; i++) {
-                assertTrue("or", (i1.testBit(i) || i2.testBit(i)) == res
-                        .testBit(i));
-            }
-        }
-    }
-
-    /**
-     * java.math.BigInteger#xor(java.math.BigInteger)
-     */
-    public void test_xorLjava_math_BigInteger() {
-        for (BigInteger[] element : booleanPairs) {
-            BigInteger i1 = element[0], i2 = element[1];
-            BigInteger res = i1.xor(i2);
-            assertTrue("symmetry of xor", res.equals(i2.xor(i1)));
-            int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
-            for (int i = 0; i < len; i++) {
-                assertTrue("xor", (i1.testBit(i) ^ i2.testBit(i)) == res
-                        .testBit(i));
-            }
-        }
-    }
-
-    /**
-     * java.math.BigInteger#not()
-     */
-    public void test_not() {
-        for (BigInteger[] element : booleanPairs) {
-            BigInteger i1 = element[0];
-            BigInteger res = i1.not();
-            int len = i1.bitLength() + 66;
-            for (int i = 0; i < len; i++) {
-                assertTrue("not", !i1.testBit(i) == res.testBit(i));
-            }
-        }
-    }
-
-    /**
-     * java.math.BigInteger#andNot(java.math.BigInteger)
-     */
-    public void test_andNotLjava_math_BigInteger() {
-        for (BigInteger[] element : booleanPairs) {
-            BigInteger i1 = element[0], i2 = element[1];
-            BigInteger res = i1.andNot(i2);
-            int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
-            for (int i = 0; i < len; i++) {
-                assertTrue("andNot", (i1.testBit(i) && !i2.testBit(i)) == res
-                        .testBit(i));
-            }
-            // asymmetrical
-            i1 = element[1];
-            i2 = element[0];
-            res = i1.andNot(i2);
-            for (int i = 0; i < len; i++) {
-                assertTrue("andNot reversed",
-                        (i1.testBit(i) && !i2.testBit(i)) == res.testBit(i));
-            }
-        }
-
-        //regression for HARMONY-4653
-        try{
-            BigInteger.ZERO.andNot(null);
-            fail("should throw NPE");
-        }catch(Exception e){
-            //expected
-        }
-        BigInteger bi = new BigInteger(0, new byte[]{});
-        assertEquals(BigInteger.ZERO, bi.andNot(BigInteger.ZERO));
-    }
-
-
-    public void testClone() {
-        // Regression test for HARMONY-1770
-        MyBigInteger myBigInteger = new MyBigInteger("12345");
-        myBigInteger = (MyBigInteger) myBigInteger.clone();
-    }
-
-    static class MyBigInteger extends BigInteger implements Cloneable {
-        public MyBigInteger(String val) {
-            super(val);
-        }
-        public Object clone() {
-            try {
-                return super.clone();
-            } catch (CloneNotSupportedException e) {
-                throw new AssertionError(e); // android-changed
-            }
-        }
-    }
-
-    @Override
-    protected void setUp() {
-        bi1 = new BigInteger("2436798324768978", 16);
-        bi2 = new BigInteger("4576829475724387584378543764555", 16);
-        bi3 = new BigInteger("43987298363278574365732645872643587624387563245",
-                16);
-
-        bi33 = new BigInteger(
-                "10730846694701319120609898625733976090865327544790136667944805934175543888691400559249041094474885347922769807001",
-                10);
-        bi22 = new BigInteger(
-                "33301606932171509517158059487795669025817912852219962782230629632224456249",
-                10);
-        bi11 = new BigInteger("6809003003832961306048761258711296064", 10);
-        bi23 = new BigInteger(
-                "597791300268191573513888045771594235932809890963138840086083595706565695943160293610527214057",
-                10);
-        bi13 = new BigInteger(
-                "270307912162948508387666703213038600031041043966215279482940731158968434008",
-                10);
-        bi12 = new BigInteger(
-                "15058244971895641717453176477697767050482947161656458456", 10);
-
-        largePos = new BigInteger(
-                "834759814379857314986743298675687569845986736578576375675678998612743867438632986243982098437620983476924376",
-                16);
-        smallPos = new BigInteger("48753269875973284765874598630960986276", 16);
-        largeNeg = new BigInteger(
-                "-878824397432651481891353247987891423768534321387864361143548364457698487264387568743568743265873246576467643756437657436587436",
-                16);
-        smallNeg = new BigInteger("-567863254343798609857456273458769843", 16);
-        booleanPairs = new BigInteger[][] { { largePos, smallPos },
-                { largePos, smallNeg }, { largeNeg, smallPos },
-                { largeNeg, smallNeg } };
-    }
-
-    private void testDiv(BigInteger i1, BigInteger i2) {
-        BigInteger q = i1.divide(i2);
-        BigInteger r = i1.remainder(i2);
-        BigInteger[] temp = i1.divideAndRemainder(i2);
-
-        assertTrue("divide and divideAndRemainder do not agree", q
-                .equals(temp[0]));
-        assertTrue("remainder and divideAndRemainder do not agree", r
-                .equals(temp[1]));
-        assertTrue("signum and equals(zero) do not agree on quotient", q
-                .signum() != 0
-                || q.equals(zero));
-        assertTrue("signum and equals(zero) do not agree on remainder", r
-                .signum() != 0
-                || r.equals(zero));
-        assertTrue("wrong sign on quotient", q.signum() == 0
-                || q.signum() == i1.signum() * i2.signum());
-        assertTrue("wrong sign on remainder", r.signum() == 0
-                || r.signum() == i1.signum());
-        assertTrue("remainder out of range", r.abs().compareTo(i2.abs()) < 0);
-        assertTrue("quotient too small", q.abs().add(one).multiply(i2.abs())
-                .compareTo(i1.abs()) > 0);
-        assertTrue("quotient too large", q.abs().multiply(i2.abs()).compareTo(
-                i1.abs()) <= 0);
-        BigInteger p = q.multiply(i2);
-        BigInteger a = p.add(r);
-        assertTrue("(a/b)*b+(a%b) != a", a.equals(i1));
-        try {
-            BigInteger mod = i1.mod(i2);
-            assertTrue("mod is negative", mod.signum() >= 0);
-            assertTrue("mod out of range", mod.abs().compareTo(i2.abs()) < 0);
-            assertTrue("positive remainder == mod", r.signum() < 0
-                    || r.equals(mod));
-            assertTrue("negative remainder == mod - divisor", r.signum() >= 0
-                    || r.equals(mod.subtract(i2)));
-        } catch (ArithmeticException e) {
-            assertTrue("mod fails on negative divisor only", i2.signum() <= 0);
-        }
-    }
-
-    private void testDivRanges(BigInteger i) {
-        BigInteger bound = i.multiply(two);
-        for (BigInteger j = bound.negate(); j.compareTo(bound) <= 0; j = j
-                .add(i)) {
-            BigInteger innerbound = j.add(two);
-            BigInteger k = j.subtract(two);
-            for (; k.compareTo(innerbound) <= 0; k = k.add(one)) {
-                testDiv(k, i);
-            }
-        }
-    }
-
-    private boolean isPrime(long b) {
-        if (b == 2) {
-            return true;
-        }
-        // check for div by 2
-        if ((b & 1L) == 0) {
-            return false;
-        }
-        long maxlen = ((long) Math.sqrt(b)) + 2;
-        for (long x = 3; x < maxlen; x += 2) {
-            if (b % x == 0) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private void testAllMults(BigInteger i1, BigInteger i2, BigInteger ans) {
-        assertTrue("i1*i2=ans", i1.multiply(i2).equals(ans));
-        assertTrue("i2*i1=ans", i2.multiply(i1).equals(ans));
-        assertTrue("-i1*i2=-ans", i1.negate().multiply(i2).equals(ans.negate()));
-        assertTrue("-i2*i1=-ans", i2.negate().multiply(i1).equals(ans.negate()));
-        assertTrue("i1*-i2=-ans", i1.multiply(i2.negate()).equals(ans.negate()));
-        assertTrue("i2*-i1=-ans", i2.multiply(i1.negate()).equals(ans.negate()));
-        assertTrue("-i1*-i2=ans", i1.negate().multiply(i2.negate()).equals(ans));
-        assertTrue("-i2*-i1=ans", i2.negate().multiply(i1.negate()).equals(ans));
-    }
-
-    private void testAllDivs(BigInteger i1, BigInteger i2) {
-        testDiv(i1, i2);
-        testDiv(i1.negate(), i2);
-        testDiv(i1, i2.negate());
-        testDiv(i1.negate(), i2.negate());
-    }
-}
diff --git a/luni/src/test/java/tests/api/java/math/OldBigIntegerTest.java b/luni/src/test/java/tests/api/java/math/OldBigIntegerTest.java
new file mode 100644
index 0000000..167ebe8
--- /dev/null
+++ b/luni/src/test/java/tests/api/java/math/OldBigIntegerTest.java
@@ -0,0 +1,372 @@
+/*
+ *  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 tests.api.java.math;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+public class OldBigIntegerTest extends junit.framework.TestCase {
+
+    BigInteger minusOne = new BigInteger("-1", 10);
+
+    BigInteger two = new BigInteger("2", 10);
+
+    BigInteger aZillion = new BigInteger("100000000000000000000000000000000000000000000000000", 10);
+
+    Random rand = new Random();
+
+    BigInteger bi;
+
+    BigInteger bi2;
+
+    BigInteger bi3;
+
+    /**
+     * java.math.BigInteger#BigInteger(int, java.util.Random)
+     */
+    public void test_ConstructorILjava_util_Random() {
+        // regression test for HARMONY-1047
+        try {
+            new BigInteger(128, (Random) null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        bi = new BigInteger(70, rand);
+        bi2 = new BigInteger(70, rand);
+        assertTrue("Random number is negative", bi.compareTo(BigInteger.ZERO) >= 0);
+        assertTrue("Random number is too big", bi.compareTo(two.pow(70)) < 0);
+        assertTrue(
+                "Two random numbers in a row are the same (might not be a bug but it very likely is)",
+                !bi.equals(bi2));
+        assertTrue("Not zero", new BigInteger(0, rand).equals(BigInteger.ZERO));
+
+        try {
+            new BigInteger(-1, (Random)null);
+            fail("IllegalArgumentException expected");
+        } catch (IllegalArgumentException e) {
+            // PASSED
+        }
+    }
+
+    /**
+     * java.math.BigInteger#BigInteger(int, int, java.util.Random)
+     */
+    // BIGNUM returns no Primes smaller than 16 bits.
+    public void test_ConstructorIILjava_util_Random() {
+        BigInteger bi1 = new BigInteger(10, 5, rand);
+        BigInteger bi2 = new BigInteger(10, 5, rand);
+        assertTrue(bi1 + " is negative", bi1.compareTo(BigInteger.ZERO) >= 0);
+        assertTrue(bi1 + " is too big", bi1.compareTo(new BigInteger("1024", 10)) < 0);
+        assertTrue(bi2 + " is negative", bi2.compareTo(BigInteger.ZERO) >= 0);
+        assertTrue(bi2 + " is too big", bi2.compareTo(new BigInteger("1024", 10)) < 0);
+
+        Random rand = new Random();
+        BigInteger bi;
+        int certainty[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+                Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -2, -1 };
+        for (int i = 2; i <= 20; i++) {
+            for (int c = 0; c < certainty.length; c++) {
+                bi = new BigInteger(i, c, rand); // Create BigInteger
+                assertEquals(i, bi.bitLength());
+            }
+        }
+
+        try {
+            new BigInteger(1, 80, (Random)null);
+            fail("ArithmeticException expected");
+        } catch (ArithmeticException expected) {
+        }
+
+        try {
+            new BigInteger(-1, (Random)null);
+            fail("IllegalArgumentException expected");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+//    public void test_SpecialPrimes() {
+//        System.out.println("test_SpecialPrimes");
+//        final BigInteger TWO = BigInteger.valueOf(2);
+//        BigInteger p, q;
+//        for (;;) {
+//            p = new BigInteger(1024, 23, new Random());
+//            q = p.subtract(BigInteger.ONE).divide(TWO);
+//            if (q.isProbablePrime(20)) {
+//                System.out.println(q);
+//                System.out.println(p);
+//                break;
+//            }
+//            System.out.print(".");
+//        }
+//        fail("isProbablePrime failed for: " + bi);
+//    }
+
+    /**
+     * java.math.BigInteger#isProbablePrime(int)
+     */
+    public void test_isProbablePrimeI() {
+        int fails = 0;
+        bi = new BigInteger(20, 20, rand);
+        if (!bi.isProbablePrime(17)) {
+            fails++;
+        }
+        bi = new BigInteger("4", 10);
+        if (bi.isProbablePrime(17)) {
+            fail("isProbablePrime failed for: " + bi);
+        }
+        bi = BigInteger.valueOf(17L * 13L);
+        if (bi.isProbablePrime(17)) {
+            fail("isProbablePrime failed for: " + bi);
+        }
+        for (long a = 2; a < 1000; a++) {
+            if (isPrime(a)) {
+                assertTrue("false negative on prime number <1000", BigInteger
+                        .valueOf(a).isProbablePrime(5));
+            } else if (BigInteger.valueOf(a).isProbablePrime(17)) {
+                System.out.println("isProbablePrime failed for: " + a);
+                fails++;
+            }
+        }
+        for (int a = 0; a < 1000; a++) {
+            bi = BigInteger.valueOf(rand.nextInt(1000000)).multiply(
+                    BigInteger.valueOf(rand.nextInt(1000000)));
+            if (bi.isProbablePrime(17)) {
+                System.out.println("isProbablePrime failed for: " + bi);
+                fails++;
+            }
+        }
+        for (int a = 0; a < 200; a++) {
+            bi = new BigInteger(70, rand).multiply(new BigInteger(70, rand));
+            if (bi.isProbablePrime(17)) {
+                System.out.println("isProbablePrime failed for: " + bi);
+                fails++;
+            }
+        }
+        assertTrue("Too many false positives - may indicate a problem",
+                fails <= 1);
+
+        //
+        // And now some tests on real big integers:
+        //
+        bi = new BigInteger("153890972191202256150310830154922163807316525358455215516067727076235016932726922093888770552128767458882963869421440585369743", 10);
+        if (!bi.isProbablePrime(80)) {
+            fail("isProbablePrime failed for: " + bi);
+        }
+        bi = new BigInteger("2090575416269141767246491983797422123741252476560371649798066134123893524014911825188890458270426076468664046568752890122415061377308817346303546688282957897504000216241497550243010257911214329646877810655164658470278901030511157372440751259674247310396158238588463284702737181653", 10);
+        if (!bi.isProbablePrime(80)) {
+            fail("isProbablePrime failed for: " + bi);
+        }
+        //
+        for (int bitLength = 100; bitLength <= 600; bitLength += 100) {
+            BigInteger a = BigInteger.probablePrime(bitLength, rand);
+            BigInteger b = BigInteger.probablePrime(bitLength, rand);
+            BigInteger c = a.multiply(b);
+            assertFalse("isProbablePrime failed for product of two large primes" +
+                            a + " * " + b + " = " + c +
+                            " (bitLength = " + bitLength + ")",
+                    c.isProbablePrime(80) );
+        }
+    }
+
+    /**
+     * java.math.BigInteger#nextProbablePrime()
+     */
+    public void test_nextProbablePrime() {
+        largePrimesProduct(
+                new BigInteger("2537895984043447429238717358455377929009126353874925049325287329295635198252046158619999217453233889378619619008359011789"),
+                new BigInteger("1711501451602688337873833423534849678524059393231999670806585630179374689152366029939952735718718709436427337762082614710093"),
+                "4343612660706993434504106787562106084038357258130862545477481433639575850237346784798851102536616749334772541987502120552264920040629526028540204698334741815536099373917351194423681128374184971846099257056996626343051832131340568120612204287123"
+        );
+
+        largePrimesProduct(
+                new BigInteger("4617974730611208463200675282934641082129817404749925308887287017217158545765190433369842932770197341032031682222405074564586462802072184047198214312142847809259437477387527466762251087500170588962277514858557309036550499896961735701485020851"),
+                new BigInteger("4313158964405728158057980867015758419530142215799386331265837224051830838583266274443105715022196238165196727467066901495701708590167750818040112544031694506528759169669442493029999154074962566165293254671176670719518898684698255068313216294333"),
+                "19918059106734861363335842730108905466210762564765297409619920041621379008685530738918145604092111306972524565803236031571858280032420140331838737621152630780261815015157696362550138161774466814661069892975003440654998880587960037013294137372709096788892473385003457361736563927256562678181177287998121131179907762285048659075843995525830945659905573174849006768920618442371027575308854641789533211132313916836205357976988977849024687805212304038260207820679964201211309384057458137851"
+        );
+    }
+
+    static void largePrimesProduct(BigInteger a, BigInteger b, String c) {
+        BigInteger wp = a.multiply(b);
+        assertFalse("isProbablePrime failed for product of two large primes" +
+                        a + " * " + b + " = " + c,
+                wp.isProbablePrime(80) );
+        BigInteger wpMinusOne = wp.subtract(BigInteger.ONE);
+        BigInteger next = wpMinusOne.nextProbablePrime();
+//        System.out.println(c);
+//        System.out.println(next);
+        assertTrue("nextProbablePrime returns wrong number: " + next +
+                        "instead of expected: " + c,
+                next.toString().equals(c) );
+    }
+
+    /**
+     * java.math.BigInteger#probablePrime(int, java.util.Random)
+     */
+    public void test_probablePrime() {
+        for (int bitLength = 50; bitLength <= 1050; bitLength += 100) {
+            BigInteger a = BigInteger.probablePrime(bitLength, rand);
+            assertTrue("isProbablePrime(probablePrime()) failed for: " + bi,
+                    a.isProbablePrime(80));
+//            System.out.println(a);
+//            BigInteger prime = a.nextProbablePrime();
+//            System.out.print("Next Probable Prime is ");
+//            System.out.println(prime);
+        }
+    }
+
+// BEGIN android-added
+//    public void testModPowPerformance() {
+//        Random rnd = new Random();
+//        for (int i = 0; i < 10; i++) {
+//            BigInteger a = new BigInteger(512, rnd);
+//            BigInteger m = new BigInteger(1024, rnd);
+//            BigInteger p = new BigInteger(256, rnd);
+//            BigInteger mp = a.modPow(p, m);
+//            System.out.println(mp);
+//        }
+//    }
+
+// shows factor 20 speed up (BIGNUM to Harmony Java):
+//    public void testNextProbablePrime() {
+//        Random rnd = new Random();
+//        rnd.setSeed(0);
+//        for (int i = 1; i <= 32; i += 1) {
+//            BigInteger a = new BigInteger(i, rnd);
+//            System.out.println(a);
+//            BigInteger prime = a.nextProbablePrime();
+//            System.out.print("Next Probable Prime is ");
+//            System.out.println(prime);
+//        }
+//        for (int i = 1; i <= 32; i += 4) {
+//            BigInteger a = new BigInteger(32 * i, rnd);
+//            System.out.println(a);
+//            BigInteger prime = a.nextProbablePrime();
+//            System.out.print("Next Probable Prime is ");
+//            System.out.println(prime);
+//        }
+//    }
+
+// shows factor 20 speed up (BIGNUM to Harmony Java):
+// shows that certainty 80 is "practically aquivalent" to certainty 100
+//    public void testPrimeGenPerformance() {
+//        Random rnd = new Random();
+//        rnd.setSeed(0);
+//        for (int i = 1; i <= 32; i +=8 ) {
+//            BigInteger a = new BigInteger(32 * i, 80, rnd);
+//            System.out.println(a);
+//            System.out.println("Now testing it again:");
+//            if (a.isProbablePrime(100)) {
+//                System.out.println("************************ PASSED! **************************");
+//            } else {
+//                System.out.println("************************ FAILED!!! **************************");
+//                System.out.println("************************ FAILED!!! **************************");
+//                System.out.println("************************ FAILED!!! **************************");
+//                System.out.println("************************ FAILED!!! **************************");
+//                System.out.println("************************ FAILED!!! **************************");
+//                System.out.println("************************ FAILED!!! **************************");
+//            }
+//        }
+//    }
+// END android-added
+
+
+
+    /**
+     * java.math.BigInteger#add(java.math.BigInteger)
+     */
+    public void test_addLjava_math_BigInteger() {
+        assertTrue("Incorrect sum--wanted a zillion", aZillion.add(aZillion)
+                .add(aZillion.negate()).equals(aZillion));
+        assertTrue("0+0", BigInteger.ZERO.add(BigInteger.ZERO).equals(BigInteger.ZERO));
+        assertTrue("0+1", BigInteger.ZERO.add(BigInteger.ONE).equals(BigInteger.ONE));
+        assertTrue("1+0", BigInteger.ONE.add(BigInteger.ZERO).equals(BigInteger.ONE));
+        assertTrue("1+1", BigInteger.ONE.add(BigInteger.ONE).equals(two));
+        assertTrue("0+(-1)", BigInteger.ZERO.add(minusOne).equals(minusOne));
+        assertTrue("(-1)+0", minusOne.add(BigInteger.ZERO).equals(minusOne));
+        assertTrue("(-1)+(-1)", minusOne.add(minusOne).equals(new BigInteger("-2", 10)));
+        assertTrue("1+(-1)", BigInteger.ONE.add(minusOne).equals(BigInteger.ZERO));
+        assertTrue("(-1)+1", minusOne.add(BigInteger.ONE).equals(BigInteger.ZERO));
+
+        for (int i = 0; i < 200; i++) {
+            BigInteger midbit = BigInteger.ZERO.setBit(i);
+            assertTrue("add fails to carry on bit " + i, midbit.add(midbit)
+                .equals(BigInteger.ZERO.setBit(i + 1)));
+        }
+        BigInteger bi2p3 = bi2.add(bi3);
+        BigInteger bi3p2 = bi3.add(bi2);
+        assertTrue("bi2p3=bi3p2", bi2p3.equals(bi3p2));
+
+
+        // BESSER UEBERGREIFENDE TESTS MACHEN IN FORM VON STRESS TEST.
+        // add large positive + small positive
+        BigInteger sum = aZillion;
+        BigInteger increment = BigInteger.ONE;
+        for (int i = 0; i < 20; i++) {
+
+        }
+
+        // add large positive + small negative
+
+        // add large negative + small positive
+
+        // add large negative + small negative
+    }
+
+    public void testClone() {
+        // Regression test for HARMONY-1770
+        MyBigInteger myBigInteger = new MyBigInteger("12345");
+        myBigInteger = (MyBigInteger) myBigInteger.clone();
+    }
+
+    static class MyBigInteger extends BigInteger implements Cloneable {
+        public MyBigInteger(String val) {
+            super(val);
+        }
+        public Object clone() {
+            try {
+                return super.clone();
+            } catch (CloneNotSupportedException e) {
+                throw new AssertionError(e); // android-changed
+            }
+        }
+    }
+
+    @Override
+    protected void setUp() {
+        bi2 = new BigInteger("4576829475724387584378543764555", 16);
+        bi3 = new BigInteger("43987298363278574365732645872643587624387563245", 16);
+    }
+
+    private boolean isPrime(long b) {
+        if (b == 2) {
+            return true;
+        }
+        // check for div by 2
+        if ((b & 1L) == 0) {
+            return false;
+        }
+        long maxlen = ((long) Math.sqrt(b)) + 2;
+        for (long x = 3; x < maxlen; x += 2) {
+            if (b % x == 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/luni/src/test/java/tests/api/java/util/CurrencyTest.java b/luni/src/test/java/tests/api/java/util/CurrencyTest.java
index c43d339..82fd7cf 100644
--- a/luni/src/test/java/tests/api/java/util/CurrencyTest.java
+++ b/luni/src/test/java/tests/api/java/util/CurrencyTest.java
@@ -17,8 +17,6 @@
 
 package tests.api.java.util;
 
-import tests.support.Support_Locale;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
diff --git a/luni/src/test/java/tests/api/java/util/LocaleTest.java b/luni/src/test/java/tests/api/java/util/LocaleTest.java
index 55c8397..7615a76 100644
--- a/luni/src/test/java/tests/api/java/util/LocaleTest.java
+++ b/luni/src/test/java/tests/api/java/util/LocaleTest.java
@@ -17,8 +17,6 @@
 
 package tests.api.java.util;
 
-import tests.support.Support_Locale;
-
 import java.security.Permission;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -168,10 +166,23 @@
         assertEquals("Failed to get locale", "fr_CA_WIN32", x.toString());
     }
 
+    /**
+     * java.util.Locale#getDisplayCountry()
+     */
+    public void test_getDisplayCountry() {
+        // Test for method java.lang.String java.util.Locale.getDisplayCountry()
+        assertTrue("Returned incorrect country: "
+                + testLocale.getDisplayCountry(), testLocale
+                .getDisplayCountry().equals("Canada"));
+
+        // Regression for Harmony-1146
+        Locale l_countryCD = new Locale("", "CD");
+        assertEquals("Congo [DRC]",
+              l_countryCD.getDisplayCountry());
+    }
+
     public void test_getDisplayCountryLjava_util_Locale() {
-        if (Support_Locale.isLocaleAvailable(Locale.ITALY)) {
-            assertEquals("Returned incorrect country", "Italie", Locale.ITALY.getDisplayCountry(l));
-        }
+        assertEquals("Italie", Locale.ITALY.getDisplayCountry(new Locale("fr", "CA", "WIN32")));
     }
 
     /**
@@ -190,19 +201,15 @@
     }
 
     public void test_getDisplayLanguageLjava_util_Locale() {
-        if (Support_Locale.isLocaleAvailable(testLocale)) {
-            assertEquals("anglais", testLocale.getDisplayLanguage(l));
-        }
+        assertEquals("anglais", new Locale("en", "CA", "WIN32").getDisplayLanguage(l));
     }
 
     public void test_getDisplayName() {
-        assertEquals("English (Canada,WIN32)", testLocale.getDisplayName());
+        assertEquals("English (Canada,WIN32)", new Locale("en", "CA", "WIN32").getDisplayName());
     }
 
     public void test_getDisplayNameLjava_util_Locale() {
-        if (Support_Locale.isLocaleAvailable(testLocale)) {
-            assertEquals("anglais (Canada,WIN32)", testLocale.getDisplayName(l));
-        }
+        assertEquals("anglais (Canada,WIN32)", new Locale("en", "CA", "WIN32").getDisplayName(l));
     }
 
     /**
@@ -343,8 +350,7 @@
      */
     public void test_toString() {
         // Test for method java.lang.String java.util.Locale.toString()
-        assertEquals("Returned incorrect string representation", "en_CA_WIN32", testLocale
-                .toString());
+        assertEquals("en_CA_WIN32", new Locale("en", "CA", "WIN32").toString());
 
         Locale l = new Locale("en", "");
         assertEquals("Wrong representation 1", "en", l.toString());
diff --git a/luni/src/test/java/tests/api/java/util/TimerTest.java b/luni/src/test/java/tests/api/java/util/TimerTest.java
index b09fa45..739c018 100644
--- a/luni/src/test/java/tests/api/java/util/TimerTest.java
+++ b/luni/src/test/java/tests/api/java/util/TimerTest.java
@@ -22,12 +22,13 @@
 import java.util.Timer;
 import java.util.TimerTask;
 import java.util.concurrent.atomic.AtomicReference;
+import junit.framework.TestCase;
 
-public class TimerTest extends junit.framework.TestCase {
+public class TimerTest extends TestCase {
 
     int timerCounter = 0;
 
-    Object sync = new Object();
+    private final Object sync = new Object();
 
     /**
      * Warning: These tests have the possibility to leave a VM hanging if the
@@ -59,14 +60,17 @@
             synchronized (this) {
                 wasRun++;
             }
-            if (incrementCount)
+            if (incrementCount) {
                 timerCounter++;
-            if (terminateCount == timerCounter && timer != null)
+            }
+            if (terminateCount == timerCounter && timer != null) {
                 timer.cancel();
+            }
             if (sleepInRun) {
                 try {
                     Thread.sleep(200);
                 } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
                 }
             }
             synchronized (sync) {
@@ -91,19 +95,16 @@
         }
     }
 
-    private void awaitRun(TimerTestTask task) {
+    private void awaitRun(TimerTestTask task) throws Exception {
         while (task.wasRun() == 0) {
-            try {
-                Thread.sleep(150);
-            } catch (InterruptedException e) {
-            }
+            Thread.sleep(150);
         }
     }
 
     /**
      * java.util.Timer#Timer(boolean)
      */
-    public void test_ConstructorZ() {
+    public void test_ConstructorZ() throws Exception {
         Timer t = null;
         try {
             // Ensure a task is run
@@ -122,7 +123,7 @@
     /**
      * java.util.Timer#Timer()
      */
-    public void test_Constructor() {
+    public void test_Constructor() throws Exception {
         Timer t = null;
         try {
             // Ensure a task is run
@@ -141,7 +142,7 @@
     /**
      * java.util.Timer#Timer(String, boolean)
      */
-    public void test_ConstructorSZ() {
+    public void test_ConstructorSZ() throws Exception {
         Timer t = null;
         try {
             // Ensure a task is run
@@ -157,23 +158,21 @@
 
         try {
             new Timer(null, true);
-            fail("NullPointerException expected");
-        } catch (NullPointerException e) {
-            //expected
+            fail();
+        } catch (NullPointerException expected) {
         }
 
         try {
             new Timer(null, false);
-            fail("NullPointerException expected");
-        } catch (NullPointerException e) {
-            //expected
+            fail();
+        } catch (NullPointerException expected) {
         }
     }
 
     /**
      * java.util.Timer#Timer(String)
      */
-    public void test_ConstructorS() {
+    public void test_ConstructorS() throws Exception {
         Timer t = null;
         try {
             // Ensure a task is run
@@ -189,31 +188,26 @@
 
         try {
             new Timer(null);
-            fail("NullPointerException expected");
-        } catch (NullPointerException e) {
-            //expected
+            fail();
+        } catch (NullPointerException expected) {
         }
     }
 
     /**
      * java.util.Timer#cancel()
      */
-    public void test_cancel() {
+    public void test_cancel() throws Exception {
         Timer t = null;
         try {
             // Ensure a task throws an IllegalStateException after cancelled
             t = new Timer();
             TimerTestTask testTask = new TimerTestTask();
             t.cancel();
-            boolean exception = false;
             try {
                 t.schedule(testTask, 100, 200);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("Scheduling a task after Timer.cancel() should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "Scheduling a task after Timer.cancel() should throw exception",
-                    exception);
 
             // Ensure a task is run but not after cancel
             t = new Timer();
@@ -222,13 +216,10 @@
             awaitRun(testTask);
             t.cancel();
             synchronized (sync) {
-                try {
-                    sync.wait(500);
-                } catch (InterruptedException e) {
-                }
+                sync.wait(500);
             }
             assertEquals("TimerTask.run() method should not have been called after cancel",
-                    1, testTask.wasRun());
+                         1, testTask.wasRun());
 
             // Ensure you can call cancel more than once
             t = new Timer();
@@ -239,13 +230,10 @@
             t.cancel();
             t.cancel();
             synchronized (sync) {
-                try {
-                    sync.wait(500);
-                } catch (InterruptedException e) {
-                }
+                sync.wait(500);
             }
             assertEquals("TimerTask.run() method should not have been called after cancel",
-                    1, testTask.wasRun());
+                         1, testTask.wasRun());
 
             // Ensure that a call to cancel from within a timer ensures no more
             // run
@@ -255,23 +243,21 @@
             testTask.terminateCount(5); // Terminate after 5 runs
             t.schedule(testTask, 100, 100);
             synchronized (sync) {
-                try {
-                    sync.wait(200);
-                    sync.wait(200);
-                    sync.wait(200);
-                    sync.wait(200);
-                    sync.wait(200);
-                    sync.wait(200);
-                } catch (InterruptedException e) {
-                }
+                sync.wait(200);
+                assertEquals(1, testTask.wasRun());
+                sync.wait(200);
+                assertEquals(2, testTask.wasRun());
+                sync.wait(200);
+                assertEquals(3, testTask.wasRun());
+                sync.wait(200);
+                assertEquals(4, testTask.wasRun());
+                sync.wait(200);
+                assertEquals(5, testTask.wasRun());
+                sync.wait(200);
+                assertEquals(5, testTask.wasRun());
             }
-            assertTrue("TimerTask.run() method should be called 5 times not "
-                    + testTask.wasRun(), testTask.wasRun() == 5);
             t.cancel();
-            try {
-                Thread.sleep(200);
-            } catch (InterruptedException e) {
-            }
+            Thread.sleep(200);
         } finally {
             if (t != null)
                 t.cancel();
@@ -316,7 +302,7 @@
     /**
      * java.util.Timer#schedule(java.util.TimerTask, java.util.Date)
      */
-    public void test_scheduleLjava_util_TimerTaskLjava_util_Date() {
+    public void test_scheduleLjava_util_TimerTaskLjava_util_Date() throws Exception {
         Timer t = null;
         try {
             // Ensure a Timer throws an IllegalStateException after cancelled
@@ -324,15 +310,11 @@
             TimerTestTask testTask = new TimerTestTask();
             Date d = new Date(System.currentTimeMillis() + 100);
             t.cancel();
-            boolean exception = false;
             try {
                 t.schedule(testTask, d);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("Scheduling a task after Timer.cancel() should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "Scheduling a task after Timer.cancel() should throw exception",
-                    exception);
 
             // Ensure a Timer throws an IllegalStateException if task already
             // cancelled
@@ -340,15 +322,11 @@
             testTask = new TimerTestTask();
             d = new Date(System.currentTimeMillis() + 100);
             testTask.cancel();
-            exception = false;
             try {
                 t.schedule(testTask, d);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("Scheduling a task after cancelling it should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "Scheduling a task after cancelling it should throw exception",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws an IllegalArgumentException if delay is
@@ -356,58 +334,41 @@
             t = new Timer();
             testTask = new TimerTestTask();
             d = new Date(-100);
-            exception = false;
             try {
                 t.schedule(testTask, d);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a task with negative date should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a task with negative date should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws a NullPointerException if the task is null
             t = new Timer();
-            exception = false;
             d = new Date(System.currentTimeMillis() + 100);
             try {
                 t.schedule(null, d);
-            } catch (NullPointerException e) {
-                exception = true;
+                fail("Scheduling a null task should throw NullPointerException");
+            } catch (NullPointerException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task should throw NullPointerException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws a NullPointerException if the date is null
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.schedule(testTask, null);
-            } catch (NullPointerException e) {
-                exception = true;
+                fail("Scheduling a null date should throw NullPointerException");
+            } catch (NullPointerException expected) {
             }
-            assertTrue(
-                    "Scheduling a null date should throw NullPointerException",
-                    exception);
             t.cancel();
 
             // Ensure proper sequence of exceptions
             t = new Timer();
             d = new Date(-100);
-            exception = false;
             try {
                 t.schedule(null, d);
-            } catch (NullPointerException e) {
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a null task with negative date should throw IllegalArgumentException first");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task with negative date should throw IllegalArgumentException first",
-                    exception);
             t.cancel();
 
             // Ensure a task is run
@@ -436,13 +397,9 @@
             testTask.incrementCount(true);
             d = new Date(System.currentTimeMillis() + 10);
             t.schedule(testTask, d);
-            try {
-                Thread.sleep(400);
-            } catch (InterruptedException e) {
-            }
-            assertTrue(
-                    "Multiple tasks should have incremented counter 4 times not "
-                            + timerCounter, timerCounter == 4);
+            Thread.sleep(400);
+            assertTrue("Multiple tasks should have incremented counter 4 times not "
+                       + timerCounter, timerCounter == 4);
             t.cancel();
         } finally {
             if (t != null)
@@ -453,79 +410,58 @@
     /**
      * java.util.Timer#schedule(java.util.TimerTask, long)
      */
-    public void test_scheduleLjava_util_TimerTaskJ() {
+    public void test_scheduleLjava_util_TimerTaskJ() throws Exception {
         Timer t = null;
         try {
             // Ensure a Timer throws an IllegalStateException after cancelled
             t = new Timer();
             TimerTestTask testTask = new TimerTestTask();
             t.cancel();
-            boolean exception = false;
             try {
                 t.schedule(testTask, 100);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("Scheduling a task after Timer.cancel() should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "Scheduling a task after Timer.cancel() should throw exception",
-                    exception);
 
             // Ensure a Timer throws an IllegalStateException if task already
             // cancelled
             t = new Timer();
             testTask = new TimerTestTask();
             testTask.cancel();
-            exception = false;
             try {
                 t.schedule(testTask, 100);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("Scheduling a task after cancelling it should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "Scheduling a task after cancelling it should throw exception",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws an IllegalArgumentException if delay is
             // negative
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.schedule(testTask, -100);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a task with negative delay should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a task with negative delay should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws a NullPointerException if the task is null
             t = new Timer();
-            exception = false;
             try {
                 t.schedule(null, 10);
-            } catch (NullPointerException e) {
-                exception = true;
+                fail("Scheduling a null task should throw NullPointerException");
+            } catch (NullPointerException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task should throw NullPointerException",
-                    exception);
             t.cancel();
 
             // Ensure proper sequence of exceptions
             t = new Timer();
-            exception = false;
             try {
                 t.schedule(null, -10);
-            } catch (NullPointerException e) {
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a null task with negative delays should throw IllegalArgumentException first");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task with negative delays should throw IllegalArgumentException first",
-                    exception);
             t.cancel();
 
             // Ensure a task is run
@@ -549,13 +485,9 @@
             testTask = new TimerTestTask();
             testTask.incrementCount(true);
             t.schedule(testTask, 10);
-            try {
-                Thread.sleep(400);
-            } catch (InterruptedException e) {
-            }
-            assertTrue(
-                    "Multiple tasks should have incremented counter 4 times not "
-                            + timerCounter, timerCounter == 4);
+            Thread.sleep(400);
+            assertTrue("Multiple tasks should have incremented counter 4 times not "
+                       + timerCounter, timerCounter == 4);
             t.cancel();
         } finally {
             if (t != null)
@@ -566,122 +498,89 @@
     /**
      * java.util.Timer#schedule(java.util.TimerTask, long, long)
      */
-    public void test_scheduleLjava_util_TimerTaskJJ() {
+    public void test_scheduleLjava_util_TimerTaskJJ() throws Exception {
         Timer t = null;
         try {
             // Ensure a Timer throws an IllegalStateException after cancelled
             t = new Timer();
             TimerTestTask testTask = new TimerTestTask();
             t.cancel();
-            boolean exception = false;
             try {
                 t.schedule(testTask, 100, 100);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("Scheduling a task after Timer.cancel() should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "Scheduling a task after Timer.cancel() should throw exception",
-                    exception);
 
             // Ensure a Timer throws an IllegalStateException if task already
             // cancelled
             t = new Timer();
             testTask = new TimerTestTask();
             testTask.cancel();
-            exception = false;
             try {
                 t.schedule(testTask, 100, 100);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("Scheduling a task after cancelling it should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "Scheduling a task after cancelling it should throw exception",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws an IllegalArgumentException if delay is
             // negative
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.schedule(testTask, -100, 100);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a task with negative delay should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a task with negative delay should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws an IllegalArgumentException if period is
             // negative
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.schedule(testTask, 100, -100);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a task with negative period should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a task with negative period should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws an IllegalArgumentException if period is
             // zero
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.schedule(testTask, 100, 0);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a task with 0 period should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a task with 0 period should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws a NullPointerException if the task is null
             t = new Timer();
-            exception = false;
             try {
                 t.schedule(null, 10, 10);
-            } catch (NullPointerException e) {
-                exception = true;
+                fail("Scheduling a null task should throw NullPointerException");
+            } catch (NullPointerException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task should throw NullPointerException",
-                    exception);
             t.cancel();
 
             // Ensure proper sequence of exceptions
             t = new Timer();
-            exception = false;
             try {
                 t.schedule(null, -10, -10);
-            } catch (NullPointerException e) {
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a null task with negative delays should throw IllegalArgumentException first");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task with negative delays should throw IllegalArgumentException first",
-                    exception);
             t.cancel();
 
             // Ensure a task is run at least twice
             t = new Timer();
             testTask = new TimerTestTask();
             t.schedule(testTask, 100, 100);
-            try {
-                Thread.sleep(400);
-            } catch (InterruptedException e) {
-            }
-            assertTrue(
-                    "TimerTask.run() method should have been called at least twice ("
-                            + testTask.wasRun() + ")", testTask.wasRun() >= 2);
+            Thread.sleep(400);
+            assertTrue("TimerTask.run() method should have been called at least twice ("
+                       + testTask.wasRun() + ")", testTask.wasRun() >= 2);
             t.cancel();
 
             // Ensure multiple tasks are run
@@ -698,13 +597,9 @@
             testTask = new TimerTestTask();
             testTask.incrementCount(true);
             t.schedule(testTask, 100, 200); // at least 4 times
-            try {
-                Thread.sleep(1200); // Allowed more room for error
-            } catch (InterruptedException e) {
-            }
-            assertTrue(
-                    "Multiple tasks should have incremented counter 24 times not "
-                            + timerCounter, timerCounter >= 24);
+            Thread.sleep(1200); // Allowed more room for error
+            assertTrue("Multiple tasks should have incremented counter 24 times not "
+                       + timerCounter, timerCounter >= 24);
             t.cancel();
         } finally {
             if (t != null)
@@ -716,7 +611,7 @@
      * java.util.Timer#schedule(java.util.TimerTask, java.util.Date,
      *        long)
      */
-    public void test_scheduleLjava_util_TimerTaskLjava_util_DateJ() {
+    public void test_scheduleLjava_util_TimerTaskLjava_util_DateJ() throws Exception {
         Timer t = null;
         try {
             // Ensure a Timer throws an IllegalStateException after cancelled
@@ -724,15 +619,11 @@
             TimerTestTask testTask = new TimerTestTask();
             Date d = new Date(System.currentTimeMillis() + 100);
             t.cancel();
-            boolean exception = false;
             try {
                 t.schedule(testTask, d, 100);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("Scheduling a task after Timer.cancel() should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "Scheduling a task after Timer.cancel() should throw exception",
-                    exception);
 
             // Ensure a Timer throws an IllegalStateException if task already
             // cancelled
@@ -740,15 +631,11 @@
             d = new Date(System.currentTimeMillis() + 100);
             testTask = new TimerTestTask();
             testTask.cancel();
-            exception = false;
             try {
                 t.schedule(testTask, d, 100);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("Scheduling a task after cancelling it should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "Scheduling a task after cancelling it should throw exception",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws an IllegalArgumentException if delay is
@@ -756,15 +643,11 @@
             t = new Timer();
             d = new Date(-100);
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.schedule(testTask, d, 100);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a task with negative delay should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a task with negative delay should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws an IllegalArgumentException if period is
@@ -772,58 +655,41 @@
             t = new Timer();
             d = new Date(System.currentTimeMillis() + 100);
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.schedule(testTask, d, -100);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a task with negative period should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a task with negative period should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws a NullPointerException if the task is null
             t = new Timer();
             d = new Date(System.currentTimeMillis() + 100);
-            exception = false;
             try {
                 t.schedule(null, d, 10);
-            } catch (NullPointerException e) {
-                exception = true;
+                fail("Scheduling a null task should throw NullPointerException");
+            } catch (NullPointerException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task should throw NullPointerException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws a NullPointerException if the date is null
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.schedule(testTask, null, 10);
-            } catch (NullPointerException e) {
-                exception = true;
+                fail("Scheduling a null task should throw NullPointerException");
+            } catch (NullPointerException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task should throw NullPointerException",
-                    exception);
             t.cancel();
 
             // Ensure proper sequence of exceptions
             t = new Timer();
             d = new Date(-100);
-            exception = false;
             try {
                 t.schedule(null, d, 10);
-            } catch (NullPointerException e) {
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a null task with negative dates should throw IllegalArgumentException first");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task with negative dates should throw IllegalArgumentException first",
-                    exception);
             t.cancel();
 
             // Ensure a task is run at least twice
@@ -831,13 +697,9 @@
             d = new Date(System.currentTimeMillis() + 100);
             testTask = new TimerTestTask();
             t.schedule(testTask, d, 100);
-            try {
-                Thread.sleep(800);
-            } catch (InterruptedException e) {
-            }
-            assertTrue(
-                    "TimerTask.run() method should have been called at least twice ("
-                            + testTask.wasRun() + ")", testTask.wasRun() >= 2);
+            Thread.sleep(800);
+            assertTrue("TimerTask.run() method should have been called at least twice ("
+                       + testTask.wasRun() + ")", testTask.wasRun() >= 2);
             t.cancel();
 
             // Ensure multiple tasks are run
@@ -858,13 +720,9 @@
             testTask.incrementCount(true);
             d = new Date(System.currentTimeMillis() + 100);
             t.schedule(testTask, d, 200); // at least 4 times
-            try {
-                Thread.sleep(3000);
-            } catch (InterruptedException e) {
-            }
-            assertTrue(
-                    "Multiple tasks should have incremented counter 24 times not "
-                            + timerCounter, timerCounter >= 24);
+            Thread.sleep(3000);
+            assertTrue("Multiple tasks should have incremented counter 24 times not "
+                       + timerCounter, timerCounter >= 24);
             t.cancel();
         } finally {
             if (t != null)
@@ -876,64 +734,48 @@
      * java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long,
      *        long)
      */
-    public void test_scheduleAtFixedRateLjava_util_TimerTaskJJ() {
+    public void test_scheduleAtFixedRateLjava_util_TimerTaskJJ() throws Exception {
         Timer t = null;
         try {
             // Ensure a Timer throws an IllegalStateException after cancelled
             t = new Timer();
             TimerTestTask testTask = new TimerTestTask();
             t.cancel();
-            boolean exception = false;
             try {
                 t.scheduleAtFixedRate(testTask, 100, 100);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("scheduleAtFixedRate after Timer.cancel() should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "scheduleAtFixedRate after Timer.cancel() should throw exception",
-                    exception);
 
             // Ensure a Timer throws an IllegalArgumentException if delay is
             // negative
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.scheduleAtFixedRate(testTask, -100, 100);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("scheduleAtFixedRate with negative delay should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "scheduleAtFixedRate with negative delay should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws an IllegalArgumentException if period is
             // negative
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.scheduleAtFixedRate(testTask, 100, -100);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("scheduleAtFixedRate with negative period should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "scheduleAtFixedRate with negative period should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a task is run at least twice
             t = new Timer();
             testTask = new TimerTestTask();
             t.scheduleAtFixedRate(testTask, 100, 100);
-            try {
-                Thread.sleep(400);
-            } catch (InterruptedException e) {
-            }
-            assertTrue(
-                    "TimerTask.run() method should have been called at least twice ("
-                            + testTask.wasRun() + ")", testTask.wasRun() >= 2);
+            Thread.sleep(400);
+            assertTrue("TimerTask.run() method should have been called at least twice ("
+                       + testTask.wasRun() + ")", testTask.wasRun() >= 2);
             t.cancel();
 
             class SlowThenFastTask extends TimerTask {
@@ -953,6 +795,7 @@
                         try {
                             Thread.sleep(200);
                         } catch (InterruptedException e) {
+                            throw new RuntimeException(e);
                         }
                     }
                 }
@@ -972,13 +815,10 @@
 
             // at least 9 times even when asleep
             t.scheduleAtFixedRate(slowThenFastTask, 100, 100);
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-            }
+            Thread.sleep(1000);
             long lastDelta = slowThenFastTask.lastDelta();
             assertTrue("Fixed Rate Schedule should catch up, but is off by "
-                    + lastDelta + " ms", slowThenFastTask.lastDelta < 300);
+                       + lastDelta + " ms", slowThenFastTask.lastDelta < 300);
             t.cancel();
         } finally {
             if (t != null)
@@ -990,96 +830,70 @@
      * java.util.Timer#scheduleAtFixedRate(java.util.TimerTask,
      *        java.util.Date, long)
      */
-    public void test_scheduleAtFixedRateLjava_util_TimerTaskLjava_util_DateJ() {
+    public void test_scheduleAtFixedRateLjava_util_TimerTaskLjava_util_DateJ() throws Exception {
         Timer t = null;
         try {
             // Ensure a Timer throws an IllegalStateException after cancelled
             t = new Timer();
             TimerTestTask testTask = new TimerTestTask();
             t.cancel();
-            boolean exception = false;
             Date d = new Date(System.currentTimeMillis() + 100);
             try {
                 t.scheduleAtFixedRate(testTask, d, 100);
-            } catch (IllegalStateException e) {
-                exception = true;
+                fail("scheduleAtFixedRate after Timer.cancel() should throw exception");
+            } catch (IllegalStateException expected) {
             }
-            assertTrue(
-                    "scheduleAtFixedRate after Timer.cancel() should throw exception",
-                    exception);
 
             // Ensure a Timer throws an IllegalArgumentException if delay is
             // negative
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             d = new Date(-100);
             try {
                 t.scheduleAtFixedRate(testTask, d, 100);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("scheduleAtFixedRate with negative Date should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "scheduleAtFixedRate with negative Date should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws an IllegalArgumentException if period is
             // negative
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.scheduleAtFixedRate(testTask, d, -100);
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("scheduleAtFixedRate with negative period should throw IllegalArgumentException");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "scheduleAtFixedRate with negative period should throw IllegalArgumentException",
-                    exception);
             t.cancel();
 
             // Ensure a Timer throws an NullPointerException if date is Null
             t = new Timer();
             testTask = new TimerTestTask();
-            exception = false;
             try {
                 t.scheduleAtFixedRate(testTask, null, 100);
-            } catch (NullPointerException e) {
-                exception = true;
+                fail("scheduleAtFixedRate with null date should throw NullPointerException");
+            } catch (NullPointerException expected) {
             }
-            assertTrue(
-                    "scheduleAtFixedRate with null date should throw NullPointerException",
-                    exception);
             t.cancel();
 
             // Ensure proper sequence of exceptions
             t = new Timer();
-            exception = false;
             d = new Date(-100);
             try {
                 t.scheduleAtFixedRate(null, d, 10);
-            } catch (NullPointerException e) {
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a null task with negative date should throw IllegalArgumentException first");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task with negative date should throw IllegalArgumentException first",
-                    exception);
             t.cancel();
 
             // Ensure proper sequence of exceptions
             t = new Timer();
-            exception = false;
             try {
                 t.scheduleAtFixedRate(null, null, -10);
-            } catch (NullPointerException e) {
-            } catch (IllegalArgumentException e) {
-                exception = true;
+                fail("Scheduling a null task & null date & negative period should throw IllegalArgumentException first");
+            } catch (IllegalArgumentException expected) {
             }
-            assertTrue(
-                    "Scheduling a null task & null date & negative period should throw IllegalArgumentException first",
-                    exception);
             t.cancel();
 
             // Ensure a task is run at least twice
@@ -1087,13 +901,9 @@
             testTask = new TimerTestTask();
             d = new Date(System.currentTimeMillis() + 100);
             t.scheduleAtFixedRate(testTask, d, 100);
-            try {
-                Thread.sleep(400);
-            } catch (InterruptedException e) {
-            }
-            assertTrue(
-                    "TimerTask.run() method should have been called at least twice ("
-                            + testTask.wasRun() + ")", testTask.wasRun() >= 2);
+            Thread.sleep(400);
+            assertTrue("TimerTask.run() method should have been called at least twice ("
+                       + testTask.wasRun() + ")", testTask.wasRun() >= 2);
             t.cancel();
 
             class SlowThenFastTask extends TimerTask {
@@ -1113,6 +923,7 @@
                         try {
                             Thread.sleep(200);
                         } catch (InterruptedException e) {
+                            throw new RuntimeException(e);
                         }
                     }
                 }
@@ -1133,13 +944,10 @@
 
             // at least 9 times even when asleep
             t.scheduleAtFixedRate(slowThenFastTask, d, 100);
-            try {
-                Thread.sleep(1000);
-            } catch (InterruptedException e) {
-            }
+            Thread.sleep(1000);
             long lastDelta = slowThenFastTask.lastDelta();
             assertTrue("Fixed Rate Schedule should catch up, but is off by "
-                    + lastDelta + " ms", lastDelta < 300);
+                       + lastDelta + " ms", lastDelta < 300);
             t.cancel();
         } finally {
             if (t != null)
@@ -1152,7 +960,7 @@
      * let those exceptions bubble up, where they will both notify the thread's
      * uncaught exception handler and terminate the timer's thread.
      */
-    public void testThrowingTaskKillsTimerThread() throws InterruptedException {
+    public void testThrowingTaskKillsTimerThread() throws Exception {
         final AtomicReference<Thread> threadRef = new AtomicReference<Thread>();
         new Timer().schedule(new TimerTask() {
             @Override public void run() {
diff --git a/luni/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java
index 31d0a12..30a1a9c 100644
--- a/luni/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java
+++ b/luni/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java
@@ -368,7 +368,7 @@
      * @throws NoSuchAlgorithmException
      * javax.net.ssl.SSLEngine#getDelegatedTask()
      */
-    @KnownFailure("org.apache.harmony.xnet.provider.jsse.SSLEngineImpl#getDelegatedTask() throws NPE instead of returning null")
+    @KnownFailure("com.android.org.conscrypt.SSLEngineImpl#getDelegatedTask() throws NPE instead of returning null")
     public void test_getDelegatedTask() throws NoSuchAlgorithmException {
         SSLEngine sse = getEngine();
         try {
diff --git a/luni/src/test/native/sub.mk b/luni/src/test/native/sub.mk
deleted file mode 100644
index 24dc52c..0000000
--- a/luni/src/test/native/sub.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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_SRC_FILES := \
-    test_openssl_engine.cpp
-
-LOCAL_C_INCLUDES += \
-    external/openssl/include
-
-LOCAL_SHARED_LIBRARIES += \
-    libcrypto
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index ae25352..bb9aeda 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -31,6 +31,7 @@
 import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import javax.crypto.spec.DHPrivateKeySpec;
@@ -99,12 +100,12 @@
             PROVIDER_ALGORITHMS.put(type, algorithms);
         }
         assertTrue("Duplicate " + type + " " + algorithm,
-                   algorithms.add(algorithm.toUpperCase()));
+                   algorithms.add(algorithm.toUpperCase(Locale.ROOT)));
     }
     private static void unprovide(String type, String algorithm) {
         Set<String> algorithms = PROVIDER_ALGORITHMS.get(type);
         assertNotNull(algorithms);
-        assertTrue(algorithm, algorithms.remove(algorithm.toUpperCase()));
+        assertTrue(algorithm, algorithms.remove(algorithm.toUpperCase(Locale.ROOT)));
         if (algorithms.isEmpty()) {
             assertNotNull(PROVIDER_ALGORITHMS.remove(type));
         }
@@ -212,6 +213,7 @@
         provide("SecretKeyFactory", "PBEWithSHA1AndDESede");
         provide("SecretKeyFactory", "PBEWithSHA1AndRC2_40");
         provide("SecretKeyFactory", "PBKDF2WithHmacSHA1");
+        provide("SecretKeyFactory", "PBKDF2WithHmacSHA1And8bit");
         provide("SecureRandom", "SHA1PRNG");
         provide("Signature", "MD2withRSA");
         provide("Signature", "MD5withRSA");
diff --git a/support/src/test/java/tests/http/MockWebServer.java b/support/src/test/java/tests/http/MockWebServer.java
index fa01380..1b776b2 100644
--- a/support/src/test/java/tests/http/MockWebServer.java
+++ b/support/src/test/java/tests/http/MockWebServer.java
@@ -36,6 +36,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Set;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
@@ -54,7 +55,7 @@
  * A scriptable web server. Callers supply canned responses and the server
  * replays them upon request in sequence.
  *
- * @deprecated prefer com.google.mockwebserver.MockWebServer
+ * @deprecated Use {@code com.google.mockwebserver.MockWebServer} instead.
  */
 @Deprecated
 public final class MockWebServer {
@@ -345,7 +346,7 @@
         String header;
         while (!(header = readAsciiUntilCrlf(in)).isEmpty()) {
             headers.add(header);
-            String lowercaseHeader = header.toLowerCase();
+            String lowercaseHeader = header.toLowerCase(Locale.ROOT);
             if (contentLength == -1 && lowercaseHeader.startsWith("content-length:")) {
                 contentLength = Integer.parseInt(header.substring(15).trim());
             }
diff --git a/support/src/test/java/tests/resources/hyts_signed_authAttrs.jar b/support/src/test/java/tests/resources/hyts_signed_authAttrs.jar
new file mode 100644
index 0000000..dded44f
--- /dev/null
+++ b/support/src/test/java/tests/resources/hyts_signed_authAttrs.jar
Binary files differ
diff --git a/support/src/test/java/tests/support/Support_DecimalFormat.java b/support/src/test/java/tests/support/Support_DecimalFormat.java
index 9baa4cc..89e226a 100644
--- a/support/src/test/java/tests/support/Support_DecimalFormat.java
+++ b/support/src/test/java/tests/support/Support_DecimalFormat.java
@@ -139,37 +139,26 @@
         Locale us = Locale.US;
         Locale tr = new Locale("de", "CH");
 
-        if (Support_Locale.isLocaleAvailable(us)) {
-            // locale dependent test, bug 1943269
+        // test number instance
+        t_Format(1, number, NumberFormat.getNumberInstance(us), getNumberVectorUS());
 
-            // test number instance
-            t_Format(1, number, NumberFormat.getNumberInstance(us),
-                    getNumberVectorUS());
+        // test integer instance
+        t_Format(2, number, NumberFormat.getIntegerInstance(us), getIntegerVectorUS());
 
-            // test integer instance
-            t_Format(2, number, NumberFormat.getIntegerInstance(us),
-                    getIntegerVectorUS());
+        // test percent instance
+        t_Format(3, number, NumberFormat.getPercentInstance(us), getPercentVectorUS());
 
-            // test percent instance
-            t_Format(3, number, NumberFormat.getPercentInstance(us),
-                    getPercentVectorUS());
+        // test currency instance with US Locale
+        t_Format(4, number, NumberFormat.getCurrencyInstance(us), getPositiveCurrencyVectorUS());
 
-            // test currency instance with US Locale
-            t_Format(4, number, NumberFormat.getCurrencyInstance(us),
-                    getPositiveCurrencyVectorUS());
+        // test negative currency instance with US Locale
+        t_Format(5, negativeNumber, NumberFormat.getCurrencyInstance(us), getNegativeCurrencyVectorUS());
 
-            // test negative currency instance with US Locale
-            t_Format(5, negativeNumber, NumberFormat.getCurrencyInstance(us),
-                    getNegativeCurrencyVectorUS());
+        // test multiple grouping separators
+        t_Format(6, longNumber, NumberFormat.getNumberInstance(us), getNumberVector2US());
 
-            // test multiple grouping seperators
-            t_Format(6, longNumber, NumberFormat.getNumberInstance(us),
-                    getNumberVector2US());
-
-            // test 0
-            t_Format(7, zeroNumber, NumberFormat.getNumberInstance(us),
-                    getZeroVector());
-        }
+        // test 0
+        t_Format(7, zeroNumber, NumberFormat.getNumberInstance(us), getZeroVector());
 
         // test permille pattern
         DecimalFormat format = new DecimalFormat("###0.##\u2030");
@@ -183,15 +172,11 @@
         format = new DecimalFormat("0000.0#E0");
         t_Format(10, number, format, getNegativeExponentVector());
 
-        if (Support_Locale.isLocaleAvailable(tr)) {
-            // test currency instance with TR Locale
-            t_Format(11, number, NumberFormat.getCurrencyInstance(tr),
-                    getPositiveCurrencyVectorCH());
+        // test currency instance with TR Locale
+        t_Format(11, number, NumberFormat.getCurrencyInstance(tr), getPositiveCurrencyVectorCH());
 
-            // test negative currency instance with TR Locale
-            t_Format(12, negativeNumber, NumberFormat.getCurrencyInstance(tr),
-                    getNegativeCurrencyVectorCH());
-        }
+        // test negative currency instance with TR Locale
+        t_Format(12, negativeNumber, NumberFormat.getCurrencyInstance(tr), getNegativeCurrencyVectorCH());
     }
 
     private static Vector<FieldContainer> getNumberVectorUS() {
diff --git a/support/src/test/java/tests/support/Support_Locale.java b/support/src/test/java/tests/support/Support_Locale.java
deleted file mode 100644
index 68f01c5..0000000
--- a/support/src/test/java/tests/support/Support_Locale.java
+++ /dev/null
@@ -1,33 +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 tests.support;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Helper class for tests that rely on locale data.
- */
-public class Support_Locale {
-    public static boolean isLocaleAvailable(Locale requiredLocale) {
-        Set<Locale> localeSet = new HashSet<Locale>(Arrays.asList(Locale.getAvailableLocales()));
-        return localeSet.contains(requiredLocale);
-    }
-}
diff --git a/support/src/test/java/tests/support/Support_PortManager.java b/support/src/test/java/tests/support/Support_PortManager.java
index 9d2fd86..b68a445 100644
--- a/support/src/test/java/tests/support/Support_PortManager.java
+++ b/support/src/test/java/tests/support/Support_PortManager.java
@@ -27,7 +27,7 @@
  * network port on the machine; however, it uses strange
  * logic, so leave it to the OS.
  *
- * @deprecated Use OS to find free ports.
+ * @deprecated Use the OS to find free ports.
  */
 public class Support_PortManager {
 
diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java
index 80fd8ca..84376ae 100644
--- a/xml/src/main/java/org/kxml2/io/KXmlParser.java
+++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java
@@ -468,7 +468,7 @@
 
         search:
         while (true) {
-            if (position + delimiter.length >= limit) {
+            if (position + delimiter.length > limit) {
                 if (start < position && returnText) {
                     if (result == null) {
                         result = new StringBuilder();
@@ -756,6 +756,9 @@
                     depth++;
                 } else if (c == ')') {
                     depth--;
+                } else if (c == -1) {
+                    throw new XmlPullParserException(
+                            "Unterminated element content spec", this, null);
                 }
                 position++;
                 c = peekCharacter();
@@ -857,7 +860,9 @@
                 position++;
                 // TODO: does this do escaping correctly?
                 String value = readValue((char) c, true, true, ValueContext.ATTRIBUTE);
-                position++;
+                if (peekCharacter() == c) {
+                    position++;
+                }
                 defineAttributeDefault(elementName, attributeName, value);
             }
         }
@@ -907,7 +912,9 @@
         if (quote == '"' || quote == '\'') {
             position++;
             entityValue = readValue((char) quote, true, false, ValueContext.ENTITY_DECLARATION);
-            position++;
+            if (peekCharacter() == quote) {
+                position++;
+            }
         } else if (readExternalId(true, false)) {
             /*
              * Map external entities to the empty string. This is dishonest,
@@ -1109,7 +1116,7 @@
                 attributes[i + 3] = readValue(delimiter, true, throwOnResolveFailure,
                         ValueContext.ATTRIBUTE);
 
-                if (delimiter != ' ') {
+                if (delimiter != ' ' && peekCharacter() == delimiter) {
                     position++; // end quote
                 }
             } else if (relaxed) {
@@ -1424,12 +1431,15 @@
         int c = peekCharacter();
         if (c != expected) {
             checkRelaxed("expected: '" + expected + "' actual: '" + ((char) c) + "'");
+            if (c == -1) {
+                return; // On EOF, don't move position beyond limit
+            }
         }
         position++;
     }
 
     private void read(char[] chars) throws IOException, XmlPullParserException {
-        if (position + chars.length >= limit && !fillBuffer(chars.length)) {
+        if (position + chars.length > limit && !fillBuffer(chars.length)) {
             checkRelaxed("expected: '" + new String(chars) + "' but was EOF");
             return;
         }